﻿==============================================================================
DOSYA ADI  : Pearl Engine.cpp
KAYNAK      : -Anti-Cheat\Pearl Guard\Pearl Engine.cpp
SISTEM      : v2369 Reconnect - ISTEMCI (Pearl Guard)
BOYUT       : 395762 bayt / 12851 satir
ACIKLAMA    : Ana anti-cheat motoru: XSafe/reconnect paket alici-satici, token yonetimi, UI panel tetikleyici
==============================================================================

--- DOSYA ICERIGI ASAGIDAKI GIBIDIR ------------------------------------

#pragma warning(disable : 4996)
#include "Pearl Engine.h"
#include "PearlGui.h"
#include <thread>
#include <future>
#include <TlHelp32.h>
#include "sha1.hpp"
#include "peb.h"
#include "LicenseSystem.h"
#include "RC5/RC5.h"
#include "CSpell.h"
#include "DateTime.h"
#include "BanSystem.h"
#include <gdiplus.h>
#include <Wininet.h>
#include <mmsystem.h>
#include <intrin.h>
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "wininet.lib")
// --- 1vs1 EVENT DEĞİŞKENLERİ (DIŞ TANIMLAMALAR) ---
extern bool g_bIs1v1Active;
extern std::string g_str1v1Player1;
extern std::string g_str1v1Player2;
extern int g_i1v1KillsP1;
extern int g_i1v1KillsP2;
extern uint8 g_i1v1MaxScore;
extern uint16 g_i1v1TimeLeft;
extern DWORD g_dw1v1LastTick;
// --------------------------------------------------
uint8 SafeReadMemoryByte(DWORD address)
{
	__try {
		return *(uint8*)address;
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {
		return 0; // Okunması yasak bir adres ise çökme, sadece 0 döndür
	}
}
using namespace Gdiplus;
xsettings::xsettings() : authority(0), nation(0), mypid(0), csrsspid(0), winlogonpid(0),
gamethread(0), sChaosPopulation(0), sChaosTimeLeft(0), sChaosEventStatus(0),
failcount(0), suspendcount(0), debugpid(0),
ExplorerPID(0), authstatus(false), pusopen(false), connected(false), driverload(false),
loginstate(false), selectnation(false), selfpatch(false), systemloaded(false),
threadstate(false), activewindow(false), speedcheck(false), memcheck(false), cameracheck(false), deviceinfo(false), gotSerial(false),
DrawnUI(false), BFTimer(false), DrawnRankBoard(false), ChaosTimer(false), GlitchDetect(false),
GlitchCheck(false), exit(false), unwantedload(false), lastfail(0), GlitchDetectTime(0), menuthread(nullptr), mainthread(nullptr),
ThreadHandle(nullptr), Zone(0), CameraView(0), RunMode(0), CurrentStun(0), SendKey(0),
LastSendCaller(0), CoordX(0), CoordZ(0), NewCoordX(0), NewCoordZ(0), CHR(0), PKT(0), MyModule(nullptr),
pOrig_GetTickCount(nullptr), pOrig_LoadLib(nullptr), MemCRCKey(0), ThreadMemCRCKey(0), MonitorMemCRCKey(0),
PacketMemCRCKey(0), GamefuncsMemCRCKey(0), ModuleCRCKey(0), ModuleStart(0), LicenseCRCKey(0), PeekMessageAddr(0),
OSMajorVersion(0), OSMinorVersion(0), OSBuildNumber(0), OSCSDVersion(0),
OSPlatformId(0), ImageSubSystem(0), ImageSubSystemMajorVersion(0), ImageSubSystemMinorVersion(0) {
	this->ProcessHandle = GetCurrentProcess();
	memset(this->serialNumber, 0, 1024);
	memset(this->modelNumber, 0, 1024);
	memset(this->szHWID, 0, 33);

	// UYARI GİDERİLDİ: Başlatılmayan değişkenler (MainInfo, ModuleInfo, szReg) sıfırlanarak C26495 uyarıları çözüldü.
	memset(&this->MainInfo, 0, sizeof(this->MainInfo));
	memset(&this->ModuleInfo, 0, sizeof(this->ModuleInfo));
	memset(this->szReg, 0, sizeof(this->szReg));
}
PSO_INFO PearlEngine::Settings = new SO_INFO;


bool isLeaderAttack = false;
bool ischeatactive = false;
bool isHideUser = false;
bool isActivedArrow = false;
bool __genieAttackMove = true;
bool isActivedCure = false;
bool StoneOfWarrior = false;
bool StoneOfRogue = false;
bool StoneOfMage = false;
bool StoneOfPriest = false;
void SendHWID();
clock_t CheckAliveTime = clock();
clock_t Real_SendTime = clock();
std::string name = "";
DWORD KO_UI_SCREEN_SIZE = 0x00DFC99C;
extern void Shutdown(string message = "");
extern string WtoString(WCHAR s[]);
extern string strToLower(string str);
DWORD adres = 0;
POINT koScreen;
std::vector<uint16> antiAFKProto = { 0 };
bool isRFastAttack = false;
bool uiINIT = false;
bool pusINIT = false;
bool tmpItemsINIT = false;
bool PusRefundINIT = false;
bool isRenderObject = true;
vector<ProcessInfo> processTMP;
string tmpGraphics = xorstr("<unknown>");
string tmpProcessor = xorstr("<unknown>");
int sSocketMerchant = 0;
int sSocketMerchantSpecial = 0;

tGetObjectBase Func_GetObjectBase;

bool hasInfArrowItem = false;
typedef struct
{
private:
	void* pVoid;
public:
	unsigned int Size;
	BYTE* Data;
}RECV_DATA;
uint32 RecvPrice = 0;
uint8 nisKC = 0;
typedef int (WINAPI* MyOldRecv) (SOCKET, uint8*, int, int);
typedef int (WSAAPI* MyRecv) (SOCKET, LPWSABUF, DWORD, LPDWORD, LPDWORD, LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
typedef int (WINAPI* MySend) (SOCKET, char*, int, int);
typedef int (WINAPI* MyConnect) (SOCKET, const sockaddr*, int);
typedef int (WSAAPI* MyWSAConnect) (SOCKET, const sockaddr*, int, LPWSABUF, LPWSABUF, LPQOS, LPQOS);
typedef int (WSAAPI* MyWSAStartup) (WORD, LPWSADATA);
typedef int (WINAPI* MyClosesocket) (SOCKET);
typedef int (WINAPI* MyTerminateProcess) (HANDLE hProcess, UINT uExitCode);
typedef int (WINAPI* MyExitProcess) (UINT uExitCode);
typedef int (WINAPI* MyLoadTBL) (const std::string& szFN);

MyRecv OrigRecv = NULL;
MySend OrigSend = NULL;
MyConnect OrigConnect = NULL;
MyWSAConnect OrigWSAConnect = NULL;
MyWSAStartup OrigWSAStartup = NULL;
MyClosesocket OrigClosesocket = NULL;
MyTerminateProcess OrigTerminateProcess = NULL;
MyExitProcess OrigExitProcess = NULL;
MyLoadTBL OrigLoadTBL = NULL;

bool allowAlive = true;
bool gameStarted = false;
bool isAlive = false;
uint32 reconnectToken = 0;
bool reconnectAcked = false;
volatile LONG reconnectUiPending = 0;
bool reconnectUiShown = false;
bool reconnectUiSuppressed = false;
uint8 reconnectUiHoldSeconds = 0;
volatile LONG reconnectRequestStay = 0;
volatile LONG reconnectRequestDisconnect = 0;
bool reconnectStayAcked = false;
volatile LONG reconnectTestDisconnecting = 0;
volatile LONG reconnectHoldExpired = 0;
volatile LONG reconnectResumeFails = 0;		// üst üste başarısız resume denemesi
volatile LONG reconnectAttemptCount = 0;	// aynı oturumda reconnect panel turu
volatile LONG reconnectUiClosePending = 0;
const int RECONNECT_UI_HOLD = 0;	// test beklemesi: soket canlı, geri sayım dönüyor
const int RECONNECT_UI_LOST = 1;	// bağlantı koptu: normal disconnect + yeniden bağlanma paneli
int reconnectUiMode = RECONNECT_UI_HOLD;
int reconnectUiLastRenderedMode = -1;
int reconnectUiLastRenderedSecond = -1;
DWORD reconnectUiPendingTime = 0;
std::string reconnectAccount;
std::string reconnectCharacter;
DWORD reconnectDiscoveryReturnAddress = 0;
DWORD reconnectDiscoveryFunctionStart = 0;
uint16 reconnectDiscoveryPort = 0;
DWORD reconnectDiscoveryCallsite = 0;
DWORD reconnectDiscoveryTarget = 0;
uint8 reconnectDiscoveryTargetType = 0;
	DWORD reconnectDiscoveryConnectExport = 0;
	DWORD reconnectDiscoveryWSAConnectExport = 0;
	DWORD reconnectDiscoveryWrapperCallsite = 0;
	DWORD reconnectDiscoveryWrapperTarget = 0;
	uint8 reconnectDiscoveryWrapperTargetType = 0;
	uint8 reconnectDiscoveryWrapperStatus = 0;
uint8 reconnectDiscoveryAsmStatus = 0;
uint8 reconnectDiscoveryAsmBytes[16] = {};
uint8 reconnectDiscoveryAsmByteCount = 0;
uint8 reconnectDiscoveryBeforeReturnBytes[32] = {};
uint8 reconnectDiscoveryBeforeReturnByteCount = 0;
uint8 reconnectDiscoveryTargetBytes[16] = {};
uint8 reconnectDiscoveryTargetByteCount = 0;
volatile LONG reconnectTransportRunning = 0;
SOCKET reconnectTransportSocket = INVALID_SOCKET;
std::queue<Packet> reconnectPacketQueue;
std::recursive_mutex reconnectPacketQueueLock;

// --- Reconnect köprüsü (bridge) ---
// Oyunun oyun sunucusu soketi öldüğünde client'a hiç hissettirmeden tüm trafik
// transport bağlantısına aktarılır; böylece oyunun kendi disconnect paneli
// hiçbir zaman açılmaz ve karakter oyunda askıda kalır. Yeniden bağlanma
// tamamlandığında tüm işlevler otomatik geri yüklenir.
const DWORD RECONNECT_AUTO_RESUME_SECONDS = 10;	// köprü kurulduktan sonra otomatik yeniden bağlanma gecikmesi
const DWORD RECONNECT_BRIDGE_FAIL_SECONDS = 20;	// resume ack gelmezse köprüyü bırak
SOCKET bridgeGameSocket = INVALID_SOCKET;
volatile LONG reconnectBridgeActive = 0;
volatile LONG bridgeIntentionalClose = 0;
DWORD bridgeStartTime = 0;
DWORD reconnectResumeStartTick = 0;
std::vector<uint8> bridgeRecvBuffer;
std::vector<uint8> bridgeSendBuffer;
std::recursive_mutex bridgeLock;

bool IsBridgeActive()
{
	return InterlockedCompareExchange(&reconnectBridgeActive, 0, 0) != 0;
}

// Panel "test beklemesi" modunda mı? (soket canlı, geri sayım dönüyor)
bool IsReconnectUiHoldMode()
{
	return reconnectUiMode == RECONNECT_UI_HOLD;
}

// Test bekleme süresi doldu mu? Dolduysa panel seçenekleri devre dışıdır:
// karakter (Yes/No'ya basılsa bile) her durumda oyundan düşürülür.
bool IsReconnectHoldExpired()
{
	return InterlockedCompareExchange(&reconnectHoldExpired, 0, 0) != 0;
}

static bool ReconnectSendAll(SOCKET socket, const uint8* data, int length);

void StartReconnectBridge(bool silent)
{
	// Premium kapısı: sunucu premiumsuz oyuncuya token dağıtmaz (ve girişte
	// revoke gönderir). Token yoksa reconnect HAKKI YOK demektir: köprü
	// açılmadan doğrudan oyunun kendi disconnect paneli gelir. Köprü bir kez
	// açılınca oyunun disconnect akışı engellendiği için bu kontrol yalnızca
	// RecvDetour/SendDetour'da değil, burada da ZORUNLUDUR.
	if (reconnectToken == 0)
	{
		printf("[RECONNECT] bridge refused: no token (premium required), normal disconnect flow\n");
		return;
	}

	if (InterlockedCompareExchange(&reconnectBridgeActive, 1, 0) != 0)
		return;

	bridgeStartTime = GetTickCount();
	reconnectResumeStartTick = 0;
	InterlockedExchange(&reconnectRequestStay, 0);
	InterlockedExchange(&reconnectResumeFails, 0);
	InterlockedExchange(&reconnectAttemptCount, 0);
	printf("[RECONNECT] bridge started, connection suspended\n");

	// Sessiz mod (resume zaten yolda) dışında reconnect panelini göster.
	if (!silent && reconnectTransportRunning == 0)
	{
		reconnectUiPendingTime = GetTickCount();
		InterlockedExchange(&reconnectUiPending, 1);
	}
}

void ReleaseReconnectBridge()
{
	InterlockedExchange(&reconnectBridgeActive, 0);
	{
		std::lock_guard<std::recursive_mutex> lock(bridgeLock);
		bridgeRecvBuffer.clear();
		bridgeSendBuffer.clear();
	}
	reconnectResumeStartTick = 0;
	printf("[RECONNECT] bridge released, client returns to normal disconnect flow\n");
}

// Aynı oturumda üst üste kaç başarısız resume denemesinde köprü bırakılıp
// normal disconnect akışına dönüleceği.
static const LONG RECONNECT_MAX_RESUME_FAILS = 3;

// Bağlantı TEKRAR koptu (2., 3. ... kopma): köprüyü BIRAKMA. Karakter oyunda
// askıda kalmaya devam etsin; reconnect paneli yeniden gösterilsin ve otomatik
// yeniden bağlanma sayacı sıfırdan başlasın. Sunucu her disconnect'te ticket'ı
// aynı token ile yenilediği için RESUME tekrar kabul edilir.
static void StartReconnectRetry()
{
	if (!IsBridgeActive())
		return;

	// Premium kapısı: revoke sonrası token sıfırlanmışsa köprü bırakılır;
	// panel yeniden arm edilmez, oyunun kendi disconnect paneli gelir.
	if (reconnectToken == 0)
	{
		printf("[RECONNECT] retry refused: no token (premium required), releasing bridge\n");
		ReleaseReconnectBridge();
		return;
	}

	if (InterlockedCompareExchange(&reconnectResumeFails, 0, 0) >= RECONNECT_MAX_RESUME_FAILS)
	{
		// Art arda başarısız denemeler: sunucuya ulaşılamıyor olabilir.
		// Köprüyü bırak; oyun kendi disconnect akışına girer.
		InterlockedExchange(&reconnectResumeFails, 0);
		ReleaseReconnectBridge();
		return;
	}

	reconnectAcked = false;
	reconnectResumeStartTick = 0;
	bridgeStartTime = GetTickCount();
	InterlockedExchange(&reconnectUiClosePending, 0);
	reconnectUiPendingTime = GetTickCount();
	InterlockedExchange(&reconnectUiPending, 1);
	InterlockedIncrement(&reconnectAttemptCount);
	printf("[RECONNECT] connection lost again, reconnect panel re-armed (attempt %ld)\n",
		InterlockedCompareExchange(&reconnectAttemptCount, 0, 0));
}

// Köprü aktifken oyunun recv çağrısı: veri gelene kadar beklet (oyun bağlantı
// kopmasını ASLA görmez), veri gelince normal şekilde döndür.
static int BridgeRecv(char* buf, int len)
{
	for (;;)
	{
		{
			std::lock_guard<std::recursive_mutex> lock(bridgeLock);
			if (!bridgeRecvBuffer.empty())
			{
				int count = len < static_cast<int>(bridgeRecvBuffer.size())
					? len : static_cast<int>(bridgeRecvBuffer.size());
				memcpy(buf, bridgeRecvBuffer.data(), count);
				bridgeRecvBuffer.erase(bridgeRecvBuffer.begin(), bridgeRecvBuffer.begin() + count);
				return count;
			}
		}

		if (!IsBridgeActive())
			return 0; // köprü bırakıldı → oyun normal disconnect akışına girer

		Sleep(5);
	}
}

// Bekleyen giden veriyi transporta boşaltır (resume tamamlandıktan sonra).
static void FlushBridgeSendBuffer(SOCKET socketHandle)
{
	if (socketHandle == INVALID_SOCKET || !reconnectAcked)
		return;

	std::vector<uint8> pending;
	{
		std::lock_guard<std::recursive_mutex> lock(bridgeLock);
		if (bridgeSendBuffer.empty())
			return;
		pending.swap(bridgeSendBuffer);
	}

	ReconnectSendAll(socketHandle, pending.data(), static_cast<int>(pending.size()));
}
DWORD KO_SET_UI_ORG = 0;
HANDLE thisProc = NULL;
DWORD KO_ADR = 0x0;
const DWORD KO_WH = 0x758;
const DWORD KO_PTR_PKT = 0x00F50FD0;
const DWORD KO_SND_FNC = 0x004A5C40;	//2369
const DWORD KO_ACC = 0x00DA4D18;
const DWORD KO_ACC_SIZE = 0x00DA4D18 + 0x10;
DWORD KO_WHISPER_GETMESSAGE_ORG = 0;
DWORD KO_WHISPER_VIEWMESAAGE_ORG = 0;
DWORD KO_WHISPER_CREATE_ORG = 0;
DWORD KO_WHISPER_OPEN_ORG = 0;
DWORD KO_WHISPER_RECV_ORG = 0;
MyOldRecv OrigOldRecv = NULL;
void LM_Send(Packet* pkt);
static DWORD WINAPI ReconnectTransportThread(LPVOID parameter);
static void PollReconnectPackets();
bool __cdecl HandlePacket(Packet pkt);

// ---------------------------------------------------------------------------
// Askı (HOLD) modunda panel yanıtı: transport soketi yerine ŞİFRELİ OYUN
// SOKETİ üzerinden gönderilir. Sunucu bu paketi askıdaki karakterin kendi
// CUser'ı üzerinde alır (XSafe_HandlePacket -> WIZ_RECONNECT); askı doğrulaması
// (token + socketID + durum SUSPENDED) oyun soketiyle otomatik ve garantili
// eşleşir. Transport soketi yalnızca gerçek kopma (LOST/RESUME) akışında
// kullanılır.
// ---------------------------------------------------------------------------
static void SendReconnectHoldResponse(uint8 requestType)
{
	if (!isAlive || reconnectToken == 0)
		return;

	// [XSafe][WIZ_RECONNECT(0xEE)][requestType][token] SByte [account][character]
		Packet pkt(XSafe, uint8(XSafeOpCodes::RECONNECT));
	pkt << requestType << reconnectToken;
	pkt.SByte();
	pkt << reconnectAccount << reconnectCharacter;

	LM_Send(&pkt);
	printf("[RECONNECT] hold response sent via game socket type=%u token=%u\n",
		requestType, reconnectToken);
}

void SendReconnectResume()
{
	if (!isAlive || reconnectToken == 0 || reconnectAccount.empty() || reconnectCharacter.empty())
		return;

	if (InterlockedCompareExchange(&reconnectTransportRunning, 1, 0) != 0)
		return;

	reconnectAcked = false;
	reconnectResumeStartTick = GetTickCount();
	CreateThread(NULL, 0, ReconnectTransportThread, NULL, 0, NULL);
}

// "Oyunda kal": sunucuya planlı reconnect test disconnect'ini iptal etmesini söyler.
void SendReconnectStay()
{
	if (!isAlive || reconnectToken == 0 || reconnectAccount.empty() || reconnectCharacter.empty())
		return;

	// Askı (HOLD) modunda oyun soketi hâlâ canlıdır: onayı transport yerine
	// doğrudan oyun bağlantısından gönder. Sunucu askıdaki oturumun kendi
	// CUser'ı üzerinde işler -> SUSPENDED -> IN_GAME (planlı disconnect iptal).
	if (IsReconnectUiHoldMode())
	{
		reconnectStayAcked = false;
		SendReconnectHoldResponse(6);	// RECONNECT_REQ_CONFIRM ("Yes" = oyunda kal)
		return;
	}

	InterlockedExchange(&reconnectRequestStay, 1);

	if (InterlockedCompareExchange(&reconnectTransportRunning, 1, 0) != 0)
		return; // transport zaten çalışıyor

	reconnectStayAcked = false;
	CreateThread(NULL, 0, ReconnectTransportThread, NULL, 0, NULL);
}

// "Şimdi disconnect": bekleme süresini beklemeden disconnect akışını başlatır.
void SendReconnectDisconnectNow()
{
	if (!isAlive || reconnectToken == 0 || reconnectAccount.empty() || reconnectCharacter.empty())
		return;

	// Askı (HOLD) modunda oyun soketi hâlâ canlıdır: "No" yanıtı da oyun
	// bağlantısından gönderilir (hemen disconnect).
	if (IsReconnectUiHoldMode())
	{
		reconnectStayAcked = false;
		SendReconnectHoldResponse(8);	// RECONNECT_REQ_DISCONNECT_NOW
		return;
	}

	InterlockedExchange(&reconnectRequestDisconnect, 1);

	if (InterlockedCompareExchange(&reconnectTransportRunning, 1, 0) != 0)
		return; // transport zaten çalışıyor

	reconnectStayAcked = false;
	CreateThread(NULL, 0, ReconnectTransportThread, NULL, 0, NULL);
}

static bool ReconnectSendAll(SOCKET socket, const uint8* data, int length)
{
	int sent = 0;
	while (sent < length)
	{
		int result = send(socket, reinterpret_cast<const char*>(data + sent), length - sent, 0);
		if (result == SOCKET_ERROR || result == 0)
			return false;
		sent += result;
	}
	return true;
}

static bool ReconnectReceiveAll(SOCKET socket, uint8* data, int length)
{
	int received = 0;
	while (received < length)
	{
		int result = recv(socket, reinterpret_cast<char*>(data + received), length - received, 0);
		if (result <= 0)
			return false;
		received += result;
	}
	return true;
}

static bool ReconnectSendPacket(SOCKET socket, Packet& packet)
{
	const uint16 payloadLength = static_cast<uint16>(packet.size() + 1);
	std::vector<uint8> frame(payloadLength + 6);
	*reinterpret_cast<uint16*>(&frame[0]) = 0x55AA;
	*reinterpret_cast<uint16*>(&frame[2]) = payloadLength;
	frame[4] = packet.GetOpcode();
	if (packet.size() > 0)
		memcpy(&frame[5], packet.contents(), packet.size());
	*reinterpret_cast<uint16*>(&frame[4 + payloadLength]) = 0xAA55;
	return ReconnectSendAll(socket, frame.data(), static_cast<int>(frame.size()));
}

static DWORD WINAPI ReconnectTransportThread(LPVOID)
{
	SOCKET socketHandle = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
	if (socketHandle == INVALID_SOCKET)
	{
		InterlockedExchange(&reconnectTransportRunning, 0);
		return 0;
	}

	sockaddr_in serverAddress = {};
	serverAddress.sin_family = AF_INET;
	serverAddress.sin_port = htons(15572);
	serverAddress.sin_addr.s_addr = inet_addr(Engine->m_connectedIP.c_str());
	if (serverAddress.sin_addr.s_addr == INADDR_NONE
		|| OrigConnect == NULL
		|| OrigConnect(socketHandle, reinterpret_cast<const sockaddr*>(&serverAddress), sizeof(serverAddress)) == SOCKET_ERROR)
	{
		closesocket(socketHandle);
		InterlockedExchange(&reconnectTransportRunning, 0);
		return 0;
	}

	reconnectTransportSocket = socketHandle;
	{
		Packet status(XSafe, uint8(XSafeOpCodes::RECONNECT));
		status << uint8(4) << uint8(1);
		if (!ReconnectSendPacket(socketHandle, status))
		{
			closesocket(socketHandle);
			reconnectTransportSocket = INVALID_SOCKET;
			InterlockedExchange(&reconnectTransportRunning, 0);
			return 0;
		}
	}
	{
		// STAY / DISCONNECT-NOW seçildiyse RESUME yerine ilgili istek gönderilir.
		const bool stay = InterlockedCompareExchange(&reconnectRequestStay, 0, 0) != 0;
		const bool disconnectNow = !stay
			&& InterlockedCompareExchange(&reconnectRequestDisconnect, 0, 0) != 0;
		if (stay)
			InterlockedExchange(&reconnectRequestStay, 0);
		if (disconnectNow)
			InterlockedExchange(&reconnectRequestDisconnect, 0);

		Packet request(XSafe, uint8(XSafeOpCodes::RECONNECT));
		if (stay)
		{
			request << uint8(6) << reconnectToken;
			request.SByte();
			request << reconnectAccount << reconnectCharacter;
		}
		else if (disconnectNow)
		{
			request << uint8(8) << reconnectToken;
			request.SByte();
			request << reconnectAccount << reconnectCharacter;
		}
		else
		{
			request << uint8(2) << reconnectToken;
			request.SByte();
			request << reconnectAccount << reconnectCharacter;
		}
		if (!ReconnectSendPacket(socketHandle, request))
		{
			closesocket(socketHandle);
			reconnectTransportSocket = INVALID_SOCKET;
			InterlockedExchange(&reconnectTransportRunning, 0);
			return 0;
		}

		if (stay || disconnectNow)
		{
			// Stay/disconnect isteği için sadece ack bekle ve çık.
			uint8 stayHeader[4] = {};
			uint8 stayFooter[2] = {};
			std::vector<uint8> stayPayload(4);
			if (ReconnectReceiveAll(socketHandle, stayHeader, sizeof(stayHeader))
				&& *reinterpret_cast<uint16*>(&stayHeader[0]) == 0x55AA
				&& *reinterpret_cast<uint16*>(&stayHeader[2]) == 4
				&& ReconnectReceiveAll(socketHandle, stayPayload.data(), 4)
				&& ReconnectReceiveAll(socketHandle, stayFooter, sizeof(stayFooter))
				&& *reinterpret_cast<uint16*>(&stayFooter[0]) == 0xAA55
				&& stayPayload[0] == XSafe
				&& stayPayload[1] == XSafeOpCodes::RECONNECT
				&& stayPayload[2] == 7)
			{
				reconnectStayAcked = stayPayload[3] == 1;
			}
			printf("[RECONNECT] stay acked=%d\n", reconnectStayAcked ? 1 : 0);

			closesocket(socketHandle);
			reconnectTransportSocket = INVALID_SOCKET;
			InterlockedExchange(&reconnectTransportRunning, 0);
			return 0;
		}
	}

	for (;;)
	{
		if (IsBridgeActive())
			FlushBridgeSendBuffer(socketHandle);

		uint8 header[4] = {};
		if (!ReconnectReceiveAll(socketHandle, header, sizeof(header)))
			break;
		if (*reinterpret_cast<uint16*>(&header[0]) != 0x55AA)
			break;

		const uint16 payloadLength = *reinterpret_cast<uint16*>(&header[2]);
		if (payloadLength == 0 || payloadLength > 65535)
			break;

		std::vector<uint8> payload(payloadLength);
		uint8 footer[2] = {};
		if (!ReconnectReceiveAll(socketHandle, payload.data(), payloadLength)
			|| !ReconnectReceiveAll(socketHandle, footer, sizeof(footer))
			|| *reinterpret_cast<uint16*>(&footer[0]) != 0xAA55)
			break;

		if (IsBridgeActive())
		{
			// Köprü modu: ham frame'i doğrudan oyunun recv akışına aktar;
			// oyun paketleri normal pipeline'ından (hkRecv_thyke → HandlePacket) işlenir.
			std::vector<uint8> frame;
			frame.reserve(static_cast<size_t>(payloadLength) + 6);
			frame.insert(frame.end(), header, header + 4);
			frame.insert(frame.end(), payload.begin(), payload.end());
			frame.insert(frame.end(), footer, footer + 2);
			{
				std::lock_guard<std::recursive_mutex> lock(bridgeLock);
				bridgeRecvBuffer.insert(bridgeRecvBuffer.end(), frame.begin(), frame.end());
			}
			continue;
		}

		if (payload[0] == XSafe && payloadLength >= 4)
		{
			Packet response(payload[0]);
			response.resize(payloadLength - 1);
			memcpy((void*)response.contents(), &payload[1], payloadLength - 1);
			uint8 subCode = 0;
			uint8 responseType = 0;
			response >> subCode >> responseType;
			if (subCode == XSafeOpCodes::RECONNECT && responseType == 3)
			{
				uint8 result = 0;
				response >> result;
				reconnectAcked = result == 1;
				if (reconnectAcked)
					InterlockedExchange(&reconnectResumeFails, 0);
				else
					InterlockedIncrement(&reconnectResumeFails);
				Packet status(XSafe, uint8(XSafeOpCodes::RECONNECT));
				status << uint8(4) << uint8(reconnectAcked ? 3 : 5);
				ReconnectSendPacket(socketHandle, status);
				if (!reconnectAcked)
					break;	// resume reddedildi: yeniden deneme turu başlatılır
				continue;
			}
		}

		Packet incoming(payload[0]);
		if (payloadLength > 1)
		{
			incoming.resize(payloadLength - 1);
			memcpy((void*)incoming.contents(), &payload[1], payloadLength - 1);
		}
		{
			std::lock_guard<std::recursive_mutex> lock(reconnectPacketQueueLock);
			reconnectPacketQueue.push(incoming);
		}
	}

	if (IsBridgeActive())
	{
		// Transport koptu (2./3. ... kopma): köprüyü koru, paneli yeniden arm et.
		if (!reconnectAcked)
			InterlockedIncrement(&reconnectResumeFails);
		StartReconnectRetry();
	}

	closesocket(socketHandle);
	reconnectTransportSocket = INVALID_SOCKET;
	InterlockedExchange(&reconnectTransportRunning, 0);
	return 0;
}

static void SendReconnectDiscovery()
{
	if (!isAlive || reconnectDiscoveryReturnAddress == 0)
		return;

	Packet discovery(XSafe, uint8(XSafeOpCodes::RECONNECT_DISCOVERY));
	discovery << static_cast<uint32>(reconnectDiscoveryReturnAddress)
		<< static_cast<uint32>(reconnectDiscoveryFunctionStart)
		<< static_cast<uint16>(reconnectDiscoveryPort)
		<< static_cast<uint32>(reconnectDiscoveryCallsite)
		<< static_cast<uint32>(reconnectDiscoveryTarget)
		<< static_cast<uint8>(reconnectDiscoveryTargetType)
		<< static_cast<uint32>(reconnectDiscoveryConnectExport)
		<< static_cast<uint32>(reconnectDiscoveryWSAConnectExport)
		<< static_cast<uint32>(reconnectDiscoveryWrapperCallsite)
		<< static_cast<uint32>(reconnectDiscoveryWrapperTarget)
		<< static_cast<uint8>(reconnectDiscoveryWrapperTargetType)
		<< static_cast<uint8>(reconnectDiscoveryWrapperStatus)
		<< static_cast<uint8>(reconnectDiscoveryAsmStatus)
		<< static_cast<uint8>(reconnectDiscoveryAsmByteCount);
	for (uint8 i = 0; i < reconnectDiscoveryAsmByteCount; ++i)
		discovery << reconnectDiscoveryAsmBytes[i];
	discovery << static_cast<uint8>(reconnectDiscoveryBeforeReturnByteCount);
	for (uint8 i = 0; i < reconnectDiscoveryBeforeReturnByteCount; ++i)
		discovery << reconnectDiscoveryBeforeReturnBytes[i];
	discovery << static_cast<uint8>(reconnectDiscoveryTargetByteCount);
	for (uint8 i = 0; i < reconnectDiscoveryTargetByteCount; ++i)
		discovery << reconnectDiscoveryTargetBytes[i];
	LM_Send(&discovery);
}

// İleri bildirim: tanımı bu dosyanın ilerisinde (satır ~856) mevcut.
static bool IsReadableAddress(DWORD address, SIZE_T length);

// SEH dışında kalan çıplak çağrı: hedef fonksiyon kilitlenirse istisna
// çağrıyı yapan fonksiyona (SafeCallUiFunc) kadar iletilir ve orada yakalanır.
__declspec(noinline) static void RawCallUiFunc(DWORD gameUiMgr, DWORD func)
{
	__asm
	{
		MOV ECX, gameUiMgr
		MOV EAX, func
		CALL EAX
	}
}

// Oyun UI fonksiyonunu güvenli çağırır. Sahne geçişi sırasında UI manager
// yarı kurulmuş/serbest olabilir; o durumda ShowAll/HideAll derin bir okuma
// ihlali üretebilir (0x00618272 / 0x002A0168). Çökmek yerine istisnayı yutarız.
static void SafeCallUiFunc(DWORD gameUiMgr, DWORD func)
{
	__try
	{
		RawCallUiFunc(gameUiMgr, func);
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		// UI manager bu turda geçersiz; sonraki poll'da tekrar denenir.
	}
}

// Oyunun kendi UI manager'ı üzerinde HideAll çağırarak oyunun disconnect
// panelini (ve diğer oyun UI'larını) gizler. Pearl'in reconnect paneli kendi
// ayrı UI manager'ında render edildiği için görünmeye devam eder.
static void HideGameDisconnectPanel()
{
	const DWORD gameUiMgr = *(DWORD*)KO_UI_MGR;
	if (gameUiMgr == 0 || !IsReadableAddress(gameUiMgr, 0x10))
		return;

	SafeCallUiFunc(gameUiMgr, KO_UI_HIDE_ALL_FUNC);

	reconnectUiSuppressed = true;
}

// Reconnect paneli kapanınca oyunun UI'sını geri yükler (disconnect paneli
// "No: stay disconnected" yolunda tekrar görünür, Yes yolunda oyun kendi
// sahne geçişinde UI'yı zaten gösterir; bu çağrı garanti sağlar).
static void RestoreGameUI()
{
	if (!reconnectUiSuppressed)
		return;

	const DWORD gameUiMgr = *(DWORD*)KO_UI_MGR;
	if (gameUiMgr == 0)
		return;

	// Manager okunabilir değilse bu turda dokunma; sonraki poll'da tekrar dene.
	if (!IsReadableAddress(gameUiMgr, 0x10))
		return;

	// Sahne geçişi tespiti: manager iki okuma arasında değişiyorsa kurulum
	// devam ediyor demektir; bu turda ShowAll çağrılmaz.
	if (*(DWORD*)KO_UI_MGR != gameUiMgr)
		return;

	// Aynı işaretçi en az 500 ms boyunca aynı kalmadan ShowAll çağrılmaz;
	// böylece Yes sonrası sahne/zone yüklemesi sırasındaki geçici manager
	// üzerinde çalışılmaz (1 sn içinde kilitlenme + atılma sorunu).
	static DWORD lastSeenMgr = 0;
	static DWORD stableSinceTick = 0;
	if (gameUiMgr != lastSeenMgr)
	{
		lastSeenMgr = gameUiMgr;
		stableSinceTick = GetTickCount();
		return;
	}
	if (GetTickCount() - stableSinceTick < 500)
		return;

	reconnectUiSuppressed = false;
	lastSeenMgr = 0;
	stableSinceTick = 0;

	SafeCallUiFunc(gameUiMgr, KO_UI_SHOW_ALL_FUNC);
}

void PollReconnectUi()
{
	PollReconnectPackets();

	// Süre bitti / disconnect uygulanıyor → bekleme panelini kapat (render thread).
	// Panel kapanınca oyunun kendi disconnect paneli engellenmez ve karakter
	// normal şekilde oyundan düşürülür.
	if (InterlockedCompareExchange(&reconnectUiClosePending, 0, 0) != 0)
	{
		InterlockedExchange(&reconnectUiClosePending, 0);
		if (Engine != NULL && Engine->m_UiMgr != NULL
			&& reconnectUiShown && Engine->m_UiMgr->uiMsgBox != NULL)
		{
			Engine->m_UiMgr->uiMsgBox->Close();
		}
		// Bayrak KOŞULSUZ sıfırlanır: uiMsgBox yoksa (ör. ESC ile kapatılmış
		// veya başka bir UI tarafından imha edilmişse) "reconnectUiShown"
		// takılı kalırdı ve open-guard'daki `reconnectUiShown` kontrolü
		// sonraki /reconnecttest panelinin render'ini kalıcı olarak engellerdi
		// (ikinci panel hiç görünmüyordu).
		reconnectUiShown = false;
	}

	const bool bridgeActive = IsBridgeActive();

	// Köprü aktifken otomatik akış:
	if (bridgeActive)
	{
		if (reconnectAcked)
		{
			// Resume tamamlandı → paneli kapat; tüm işlevler geri yüklendi.
			if (reconnectUiShown && Engine != NULL && Engine->m_UiMgr != NULL
				&& Engine->m_UiMgr->uiMsgBox != NULL)
			{
				Engine->m_UiMgr->uiMsgBox->Close();
			}
			// Bayrak koşulsuz sıfırlanır (uiMsgBox yoksa takılı kalırdı →
			// sonraki /reconnecttest paneli render edilemezdi).
			reconnectUiShown = false;
			reconnectResumeStartTick = 0;
			InterlockedExchange(&reconnectResumeFails, 0);
			InterlockedExchange(&reconnectAttemptCount, 0);
		}
		else if (reconnectResumeStartTick != 0
			&& reconnectTransportRunning == 0
			&& GetTickCount() - reconnectResumeStartTick > RECONNECT_BRIDGE_FAIL_SECONDS * 1000)
		{
			// Resume başarısız → köprüyü bırak; oyun normal disconnect akışına döner.
			ReleaseReconnectBridge();
		}
		else if (reconnectResumeStartTick == 0
			&& reconnectTransportRunning == 0
			&& GetTickCount() - bridgeStartTime > RECONNECT_AUTO_RESUME_SECONDS * 1000)
		{
			// Kullanıcı seçim yapmadı → süre doldu, otomatik yeniden bağlan.
			printf("[RECONNECT] auto resume started\n");
			SendReconnectResume();
		}
	}

	// Panel metni/gizleme davranışı moda göre:
	//  - HOLD : test beklemesi; geri sayım akar, oyunun disconnect paneli gizlenir.
	//  - LOST : disconnect uygulandı; oyunun kendi disconnect paneli görünür,
	//           üstte yeniden bağlanma paneli kalır.
	if (reconnectUiShown) {
		if (!bridgeActive && reconnectUiMode == RECONNECT_UI_HOLD)
			HideGameDisconnectPanel();
		else
			RestoreGameUI();
	}
	else
	{
		RestoreGameUI();
	}

	// Premium kapısı: token yoksa bekleyen reconnect paneli bayrağı temizlenir.
	// Böylece stale bir reconnectUiPending, oyunun kendi disconnect panelini
	// geciktirmez/engellemez; kopmada normal disconnect akışı işler.
	if (reconnectToken == 0
		&& InterlockedCompareExchange(&reconnectUiPending, 0, 0) != 0)
	{
		InterlockedExchange(&reconnectUiPending, 0);
		printf("[RECONNECT] stale UI pending cleared: no token (premium required)\n");
	}

	// Panel açıkken içeriği güncelle: HOLD modunda geri sayım + çubuk,
	// mod değişince (LOST) metin otomatik değişir.
	if (reconnectUiShown && !IsBridgeActive()
		&& Engine != NULL && Engine->m_UiMgr != NULL
		&& Engine->m_UiMgr->uiMsgBox != NULL)
	{
		int second = -1;
		if (reconnectUiMode == RECONNECT_UI_HOLD && reconnectUiHoldSeconds > 0)
		{
			DWORD elapsed = (GetTickCount() - reconnectUiPendingTime) / 1000;
			second = elapsed < reconnectUiHoldSeconds
				? static_cast<int>(reconnectUiHoldSeconds - elapsed) : 0;

			if (second == 0)
			{
				// Süre doldu: artık hiçbir seçenek oyunda tutmaz,
				// karakter her durumda oyundan düşürülür.
				InterlockedExchange(&reconnectHoldExpired, 1);
				InterlockedExchange(&reconnectUiClosePending, 1);
			}
		}

		if (reconnectUiMode != reconnectUiLastRenderedMode
			|| second != reconnectUiLastRenderedSecond)
		{
			reconnectUiLastRenderedMode = reconnectUiMode;
			reconnectUiLastRenderedSecond = second;

			char message[256] = {};
			if (reconnectUiMode == RECONNECT_UI_HOLD)
			{
				const int total = reconnectUiHoldSeconds > 0 ? reconnectUiHoldSeconds : 1;
				int filled = (second * 20) / total;
				if (filled < 0) filled = 0;
				if (filled > 20) filled = 20;

				char bar[24] = {};
				for (int i = 0; i < 20; ++i)
					bar[i] = i < filled ? '#' : '-';
				bar[20] = '\0';

				sprintf_s(message, sizeof(message),
					"Reconnect test running.\n[%s] %d seconds\n\nYes: stay in the game.\nNo: disconnect now.",
					bar, second < 0 ? 0 : second);
			}
			else
			{
				sprintf_s(message, sizeof(message),
					"Connection to the game server was lost.\n\nYes: reconnect now.\nNo: stay disconnected.");
			}

			Engine->m_UiMgr->uiMsgBox->SetTitle("Reconnect");
			Engine->m_UiMgr->uiMsgBox->SetMessage(message);
		}
	}

	if (InterlockedCompareExchange(&reconnectUiPending, 0, 0) == 0
		|| reconnectUiShown
		|| IsReconnectHoldExpired()
		|| reconnectToken == 0
		|| Engine == NULL
		|| Engine->m_UiMgr == NULL)
		return;

	InterlockedExchange(&reconnectUiPending, 0);
	reconnectUiShown = true;
	reconnectUiLastRenderedMode = -1;
	reconnectUiLastRenderedSecond = -1;

	char message[256] = {};
	if (IsBridgeActive())
	{
		// Bağlantı gerçekten koptu → karakter oyunda askıda tutuluyor,
		// süre dolunca otomatik yeniden bağlanılır.
		sprintf_s(message, sizeof(message),
			"Connection to the game server was lost.\nYour character is being held in the game; reconnecting automatically in %u seconds.\n\nYes: reconnect now.\nNo: disconnect.",
			RECONNECT_AUTO_RESUME_SECONDS);
	}
	else if (reconnectUiMode == RECONNECT_UI_HOLD)
	{
		// Planlı test: "Yes" oyunda kalır, "No" disconnect'i hemen uygular.
		sprintf_s(message, sizeof(message),
			"Reconnect test running.\n[--------------------] %u seconds\n\nYes: stay in the game.\nNo: disconnect now.",
			reconnectUiHoldSeconds);
	}
	else
	{
		sprintf_s(message, sizeof(message),
			"Connection to the game server was lost.\n\nYes: reconnect now.\nNo: stay disconnected.");
	}

	Engine->m_UiMgr->ShowMessageBox(
		"Reconnect",
		message,
		MsgBoxTypes::YesNo,
		ParentTypes::PARENT_RECONNECT);
}

static void PollReconnectPackets()
{
	for (;;)
	{
		Packet packet;
		{
			std::lock_guard<std::recursive_mutex> lock(reconnectPacketQueueLock);
			if (reconnectPacketQueue.empty())
				return;
			packet = reconnectPacketQueue.front();
			reconnectPacketQueue.pop();
		}

		HandlePacket(packet);
	}
}

static DWORD FindNearbyFunctionStart(DWORD address)
{
	if (address == 0)
		return 0;

	MEMORY_BASIC_INFORMATION memoryInfo = {};
	if (VirtualQuery(reinterpret_cast<const void*>(address), &memoryInfo, sizeof(memoryInfo)) == 0)
		return 0;

	const BYTE* imageBase = reinterpret_cast<const BYTE*>(memoryInfo.AllocationBase);
	const IMAGE_DOS_HEADER* dosHeader = reinterpret_cast<const IMAGE_DOS_HEADER*>(imageBase);
	if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
		return 0;

	const IMAGE_NT_HEADERS* ntHeaders = reinterpret_cast<const IMAGE_NT_HEADERS*>(imageBase + dosHeader->e_lfanew);
	if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
		return 0;

	const DWORD imageStart = reinterpret_cast<DWORD>(imageBase);
	const DWORD imageEnd = imageStart + ntHeaders->OptionalHeader.SizeOfImage;
	if (address < imageStart || address >= imageEnd)
		return 0;

	const BYTE* cursor = reinterpret_cast<const BYTE*>(address);
	for (DWORD offset = 0; offset < 0x2000 && address >= imageStart + offset + 3; ++offset)
	{
		const BYTE* candidate = cursor - offset;
		const bool standardFrame = candidate[0] == 0x55 && candidate[1] == 0x8B && candidate[2] == 0xEC;
		const bool savedRegisters = candidate[0] == 0x53 && candidate[1] == 0x8B;
		const bool stackFrame = candidate[0] == 0x83 && candidate[1] == 0xEC;
		const bool largeStackFrame = candidate[0] == 0x81 && candidate[1] == 0xEC;
		if (standardFrame || savedRegisters || stackFrame || largeStackFrame)
			return reinterpret_cast<DWORD>(candidate);
	}

	return 0;
}

static bool IsReadableAddress(DWORD address, SIZE_T length)
{
	MEMORY_BASIC_INFORMATION memoryInfo = {};
	if (VirtualQuery(reinterpret_cast<const void*>(address), &memoryInfo, sizeof(memoryInfo)) == 0)
		return false;

	if (memoryInfo.State != MEM_COMMIT || (memoryInfo.Protect & PAGE_GUARD) != 0)
		return false;

	const DWORD regionEnd = reinterpret_cast<DWORD>(memoryInfo.BaseAddress) + static_cast<DWORD>(memoryInfo.RegionSize);
	return address >= reinterpret_cast<DWORD>(memoryInfo.BaseAddress)
		&& address <= regionEnd
		&& length <= regionEnd - address;
}

static DWORD ResolveReconnectCallTarget(DWORD callAddress, BYTE opcode)
{
	if (opcode == 0xE8 && IsReadableAddress(callAddress + 1, sizeof(int32)))
	{
		int32 relative = 0;
		memcpy(&relative, reinterpret_cast<const void*>(callAddress + 1), sizeof(relative));
		return callAddress + 5 + relative;
	}

	if (opcode == 0xFF && IsReadableAddress(callAddress + 2, sizeof(DWORD))
		&& *reinterpret_cast<const BYTE*>(callAddress + 1) == 0x15)
	{
		DWORD importAddress = 0;
		memcpy(&importAddress, reinterpret_cast<const void*>(callAddress + 2), sizeof(importAddress));
		if (IsReadableAddress(importAddress, sizeof(DWORD)))
			return *reinterpret_cast<const DWORD*>(importAddress);
	}

	return 0;
}

static void ProbeReconnectAssembly(DWORD functionStart)
{
	static bool probed = false;
	if (probed)
		return;

	if (functionStart == 0)
	{
		reconnectDiscoveryAsmStatus = 1;
		printf("[RECONNECT_ASM] status=NO_CANDIDATE\n");
		return;
	}

	MEMORY_BASIC_INFORMATION memoryInfo = {};
	if (VirtualQuery(reinterpret_cast<const void*>(functionStart), &memoryInfo, sizeof(memoryInfo)) == 0)
	{
		reconnectDiscoveryAsmStatus = 2;
		printf("[RECONNECT_ASM] status=VIRTUAL_QUERY_FAILED candidate=0x%08X\n", functionStart);
		return;
	}

	const DWORD regionStart = reinterpret_cast<DWORD>(memoryInfo.BaseAddress);
	const DWORD regionEnd = regionStart + static_cast<DWORD>(memoryInfo.RegionSize);
	if (functionStart < regionStart || functionStart >= regionEnd || (memoryInfo.Protect & PAGE_GUARD) != 0)
	{
		reconnectDiscoveryAsmStatus = 3;
		printf("[RECONNECT_ASM] status=UNREADABLE candidate=0x%08X region=0x%08X-0x%08X protect=0x%08X\n",
			functionStart, regionStart, regionEnd, memoryInfo.Protect);
		return;
	}

	const DWORD scanLength = min<DWORD>(0x100, regionEnd - functionStart);
	if (scanLength < 8)
	{
		reconnectDiscoveryAsmStatus = 4;
		printf("[RECONNECT_ASM] status=SHORT_REGION candidate=0x%08X length=%u\n", functionStart, scanLength);
		return;
	}

	probed = true;
	const DWORD connectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "connect"));
	const DWORD wsaConnectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "WSAConnect"));
		reconnectDiscoveryConnectExport = connectTarget;
		reconnectDiscoveryWSAConnectExport = wsaConnectTarget;
	const BYTE* code = reinterpret_cast<const BYTE*>(functionStart);
	reconnectDiscoveryAsmStatus = 5;
	reconnectDiscoveryAsmByteCount = static_cast<uint8>(min<DWORD>(16, scanLength));
	memcpy(reconnectDiscoveryAsmBytes, code, reconnectDiscoveryAsmByteCount);

	char message[512] = {};
	int written = sprintf_s(message, sizeof(message), "[RECONNECT_ASM] candidate=0x%08X bytes=", functionStart);
	for (DWORD i = 0; i < min<DWORD>(16, scanLength) && written > 0 && written < static_cast<int>(sizeof(message)); ++i)
		written += sprintf_s(message + written, sizeof(message) - written, "%02X%s", code[i], i == 15 ? "" : " ");

	printf("%s\n", message);
	OutputDebugStringA(message);

	for (DWORD offset = 0; offset + 1 < scanLength; ++offset)
	{
		BYTE opcode = code[offset];
		if (opcode != 0xE8 && !(opcode == 0xFF && offset + 1 < 0x100 && code[offset + 1] == 0x15))
			continue;

		DWORD target = ResolveReconnectCallTarget(functionStart + offset, opcode);
		if (target == 0)
			continue;

		if (reconnectDiscoveryCallsite == 0 && (target == connectTarget || target == wsaConnectTarget))
		{
			reconnectDiscoveryCallsite = functionStart + offset;
			reconnectDiscoveryTarget = target;
			reconnectDiscoveryTargetType = target == connectTarget ? 1 : 2;
		}

		char callMessage[256] = {};
		sprintf_s(callMessage, sizeof(callMessage),
			"[RECONNECT_ASM] callsite=0x%08X target=0x%08X connect=%s wsaconnect=%s\n",
			functionStart + offset, target,
			target == connectTarget ? "YES" : "NO",
			target == wsaConnectTarget ? "YES" : "NO");
		printf("%s", callMessage);
		OutputDebugStringA(callMessage);
	}
}

static void ProbeReconnectCallsiteBeforeReturn(DWORD returnAddress)
{
	if (reconnectDiscoveryCallsite != 0 || returnAddress == 0)
		return;

	const DWORD connectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "connect"));
	const DWORD wsaConnectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "WSAConnect"));
	const DWORD contextStart = returnAddress > 32 ? returnAddress - 32 : returnAddress;
	if (IsReadableAddress(contextStart, returnAddress - contextStart))
	{
		reconnectDiscoveryBeforeReturnByteCount = static_cast<uint8>(returnAddress - contextStart);
		memcpy(reconnectDiscoveryBeforeReturnBytes,
			reinterpret_cast<const void*>(contextStart),
			reconnectDiscoveryBeforeReturnByteCount);
	}

	for (DWORD length = 2; length <= 32; ++length)
	{
		const DWORD callAddress = returnAddress - length;
		if (!IsReadableAddress(callAddress, length))
			continue;

		const BYTE opcode = *reinterpret_cast<const BYTE*>(callAddress);
		const BYTE second = *reinterpret_cast<const BYTE*>(callAddress + 1);
		const bool registerCall = opcode == 0xFF && (second & 0xF8) == 0xD0;
		if (opcode != 0xE8 && !(opcode == 0xFF && IsReadableAddress(callAddress + 1, 5)) && !registerCall)
			continue;

		if (registerCall)
		{
			printf("[RECONNECT_ASM] indirect-call callsite=0x%08X bytes=%02X %02X target=register\n",
				callAddress, opcode, second);
			continue;
		}

		DWORD target = ResolveReconnectCallTarget(callAddress, opcode);
		if (opcode == 0xE8 && callAddress + 5 == returnAddress)
		{
			reconnectDiscoveryCallsite = callAddress;
			reconnectDiscoveryTarget = target;
			reconnectDiscoveryTargetType = 3;
			if (target != 0 && IsReadableAddress(target, sizeof(reconnectDiscoveryTargetBytes)))
			{
				reconnectDiscoveryTargetByteCount = sizeof(reconnectDiscoveryTargetBytes);
				memcpy(reconnectDiscoveryTargetBytes, reinterpret_cast<const void*>(target), reconnectDiscoveryTargetByteCount);
			}
			printf("[RECONNECT_ASM] callsite=0x%08X target=0x%08X connect=DIRECT wsaconnect=NO source=return-before\n",
				callAddress, target);
			return;
		}

		if (target != connectTarget && target != wsaConnectTarget)
			continue;

		reconnectDiscoveryCallsite = callAddress;
		reconnectDiscoveryTarget = target;
		reconnectDiscoveryTargetType = target == connectTarget ? 1 : 2;

		printf("[RECONNECT_ASM] callsite=0x%08X target=0x%08X connect=%s wsaconnect=%s source=return-before\n",
			callAddress, target,
			target == connectTarget ? "YES" : "NO",
			target == wsaConnectTarget ? "YES" : "NO");
		return;
	}
}

static void ProbeReconnectWrapperBody(DWORD wrapperAddress)
{
	if (wrapperAddress == 0)
	{
		reconnectDiscoveryWrapperStatus = 1;
		return;
	}

	MEMORY_BASIC_INFORMATION memoryInfo = {};
	if (VirtualQuery(reinterpret_cast<const void*>(wrapperAddress), &memoryInfo, sizeof(memoryInfo)) == 0)
	{
		reconnectDiscoveryWrapperStatus = 2;
		return;
	}

	const DWORD regionStart = reinterpret_cast<DWORD>(memoryInfo.BaseAddress);
	const DWORD regionEnd = regionStart + static_cast<DWORD>(memoryInfo.RegionSize);
	if (wrapperAddress < regionStart || wrapperAddress >= regionEnd || (memoryInfo.Protect & PAGE_GUARD) != 0)
	{
		reconnectDiscoveryWrapperStatus = 3;
		return;
	}

	const DWORD scanLength = min<DWORD>(0x1000, regionEnd - wrapperAddress);
	if (scanLength < 6)
	{
		reconnectDiscoveryWrapperStatus = 4;
		return;
	}

	reconnectDiscoveryWrapperStatus = 5;

	const DWORD connectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "connect"));
	const DWORD wsaConnectTarget = reinterpret_cast<DWORD>(GetProcAddress(GetModuleHandleA("Ws2_32.dll"), "WSAConnect"));
	const BYTE* code = reinterpret_cast<const BYTE*>(wrapperAddress);

	for (DWORD offset = 0; offset + 5 <= scanLength; ++offset)
	{
		const BYTE opcode = code[offset];
		if (opcode == 0xFF && (code[offset + 1] & 0xF8) == 0xD0)
		{
			printf("[RECONNECT_ASM] wrapper-indirect-call=0x%08X bytes=%02X %02X target=register\n",
				wrapperAddress + offset, opcode, code[offset + 1]);
			continue;
		}

		if (opcode != 0xE8 && !(opcode == 0xFF && offset + 6 <= scanLength && code[offset + 1] == 0x15))
			continue;

		DWORD target = ResolveReconnectCallTarget(wrapperAddress + offset, opcode);
		if (target != connectTarget && target != wsaConnectTarget)
			continue;

		reconnectDiscoveryWrapperCallsite = wrapperAddress + offset;
		reconnectDiscoveryWrapperTarget = target;
		reconnectDiscoveryWrapperTargetType = target == connectTarget ? 1 : 2;
		reconnectDiscoveryWrapperStatus = 6;
		printf("[RECONNECT_ASM] wrapper-callsite=0x%08X target=0x%08X connect=%s wsaconnect=%s\n",
			wrapperAddress + offset, target,
			target == connectTarget ? "YES" : "NO",
			target == wsaConnectTarget ? "YES" : "NO");
		return;
	}

	printf("[RECONNECT_ASM] wrapper-callsite=NOT_FOUND wrapper=0x%08X\n", wrapperAddress);
	reconnectDiscoveryWrapperStatus = 7;
}

static void LogCapConnectDiscovery(const sockaddr* address)
{
	const DWORD returnAddress = reinterpret_cast<DWORD>(_ReturnAddress());
	const DWORD functionStart = FindNearbyFunctionStart(returnAddress);
	ProbeReconnectAssembly(functionStart);
	ProbeReconnectCallsiteBeforeReturn(returnAddress);
	ProbeReconnectWrapperBody(reconnectDiscoveryTarget);
	const sockaddr_in* addressIn = reinterpret_cast<const sockaddr_in*>(address);
	const unsigned short port = addressIn == NULL ? 0 : ntohs(addressIn->sin_port);
	reconnectDiscoveryReturnAddress = returnAddress;
	reconnectDiscoveryFunctionStart = functionStart;
	reconnectDiscoveryPort = port;

	MEMORY_BASIC_INFORMATION memoryInfo = {};
	VirtualQuery(reinterpret_cast<const void*>(returnAddress), &memoryInfo, sizeof(memoryInfo));
	const DWORD moduleBase = reinterpret_cast<DWORD>(memoryInfo.AllocationBase);

	const BYTE* returnBytes = reinterpret_cast<const BYTE*>(returnAddress);
	char message[512] = {};
	sprintf_s(message, sizeof(message),
		"[RECONNECT_DISCOVERY] return=0x%08X candidate=0x%08X module=0x%08X port=%u bytes=%02X %02X %02X %02X %02X %02X %02X %02X\n",
		returnAddress, functionStart, moduleBase, port,
		returnBytes[0], returnBytes[1], returnBytes[2], returnBytes[3],
		returnBytes[4], returnBytes[5], returnBytes[6], returnBytes[7]);
	printf("%s", message);
	OutputDebugStringA(message);
}
void __stdcall LM_Shutdown(std::string log, std::string graphicCards = tmpGraphics, std::string processor = tmpProcessor);
void LM_SendProcess(uint16 toWHO);

const DWORD KO_FNSBB = KO_FNSB;
void ASMPatch(DWORD dst, char* src, int size)
{
	DWORD oldprotect;
	VirtualProtect((LPVOID)dst, size, PAGE_EXECUTE_READWRITE, &oldprotect);
	memcpy((LPVOID)dst, src, size);
	VirtualProtect((LPVOID)dst, size, oldprotect, &oldprotect);
}
CSpell* GetSkillBase(int iSkillID)
{
	DWORD retval = 0;
	__asm {
		mov ecx, KO_SMMB
		mov ecx, DWORD PTR DS : [ecx]
		push iSkillID
		call KO_FNSBB
		mov retval, eax
	}
	return (CSpell*)retval;
}
bool CheckSkill(DWORD skillID)
{
	if (skillID == 106725 || skillID == 106735 || skillID == 106760 || skillID == 206725 || skillID == 206735 || skillID == 206760 || skillID == 106775 || skillID == 206775 || skillID == 900111)
		return true;

	CSpell* spell = GetSkillBase(skillID);
	if (spell) {
		auto itcrc = Engine->skillcrc.find(spell->dwID + 2031);
		if (itcrc != Engine->skillcrc.end())
		{
			// UYARI GİDERİLDİ: (uint32_t)-1 cast eklendi
			SpellCRC crc(crc32((uint8*)(DWORD)spell, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)spell + 0xB4), 0x2C, (uint32_t)-1));
			return itcrc->second.part1 == crc.part1 && itcrc->second.part2 == crc.part2;
		}
	}
	return false;
}

// myTick() içindeki tüm crc32 güncellemeleri şu formatta olmalı:
// SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));

// Nick renk, tip değiştirme
std::string objTMPStringX = "";
void SetNameString(DWORD userBase, std::string text, DWORD color, DWORD fontStyle)
{
	(void)fontStyle; // UYARI GİDERİLDİ (C4100)
	if (!userBase)
		return;

	DWORD fontBase = *(DWORD*)(userBase + 0x400/*0x3AC*/);

	if (IsBadReadPtr((void*)fontBase, sizeof(DWORD)))
		return;
	if (!fontBase)
		return;

	objTMPStringX = text;
	__asm {
		push fontStyle
		push offset objTMPStringX
		mov ecx, fontBase
		call KO_UIF_SET_FONT_STRING
	}

	if (color != 0)
	{
		*(DWORD*)(userBase + 0x738) = color;
		*(DWORD*)(fontBase + 0x44) = color;
	}
}
bool IfFileExists(char* filepath) {
	FILE* file = nullptr;
	fopen_s(&file, filepath, "r");
	if (file == nullptr) {
		return false;
	}
	fclose(file);
	return true;
}

#define LICENSETIME __TIMESTAMP__
#define SVERSION "A710225"
#define TM_YEAR_BASE 2025


unsigned long PearlEngine::GetPEB() {
	unsigned long result;
	_asm
	{
		mov eax, dword ptr fs : [0x30]
		mov result, eax;
	}
	return result;
}

void PearlEngine::SetOSVersion() {
	auto pPEB = reinterpret_cast<PPEB>(GetPEB());
	Settings->OSMajorVersion = pPEB->OSMajorVersion;
	Settings->OSMinorVersion = pPEB->OSMinorVersion;
	Settings->OSBuildNumber = pPEB->OSBuildNumber;
	Settings->OSCSDVersion = pPEB->OSCSDVersion;
	Settings->ImageSubSystemMinorVersion = pPEB->ImageSubSystemMinorVersion;
	Settings->ImageSubSystemMajorVersion = pPEB->ImageSubSystemMajorVersion;
	Settings->OSPlatformId = pPEB->OSPlatformId;
	Settings->ImageSubSystem = pPEB->ImageSubSystem;
}
void PearlEngine::NewSystemLogger(const char* logit, ...) {
	if (logit == nullptr) {
		return;
	}
	auto message = static_cast<char*>(malloc(sizeof(char) * 1024));
	if (message == nullptr) return;

	va_list argList;
	va_start(argList, logit);
	auto len = _vscprintf(logit, argList) + 1;
	vsprintf_s(message, len, logit, argList);
	va_end(argList);
	time_t rawtime;
	struct tm ptm;
	time(&rawtime);
	localtime_s(&ptm, &rawtime);

	FILE* soacslog = nullptr;
	/*fopen_s(&soacslog, "LordACS_Log.txt", "a+");*/
	if (soacslog != nullptr) {
		char text[2048]; memset(text, 0, 2048);
		sprintf_s(text, "-- %04d/%02d/%02d %02d:%02d:%02d [Game debug] %s \n", TM_YEAR_BASE + ptm.tm_year, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, message);
		fprintf_s(soacslog, "%s", text);

		// UYARI VE ÇÖKME (CRASH) GİDERİLDİ: Sadece dosya açıksa kapatılması sağlandı.
		fclose(soacslog);
	}
	free(message);
	free(argList);
}

void InterceptCall(unsigned long Offset, void* func) {
	char* yareyare;
	unsigned long oldProtect = 0; // UYARI GİDERİLDİ: İlk değer ataması (0) yapıldı
	unsigned long Dummy = 0;      // UYARI GİDERİLDİ: İlk değer ataması (0) yapıldı
	char Buffer[] = "\xE8\x00\x00\x00\x00";
	yareyare = reinterpret_cast<char*>(Offset);
	VirtualProtect(yareyare, 5L, PAGE_EXECUTE_READWRITE, &oldProtect);
	*reinterpret_cast<long*>(Buffer + 1) = reinterpret_cast<long>(func) - reinterpret_cast<long>(yareyare) - 5;
	*Buffer = static_cast<unsigned char>(0xE8);
	RtlMoveMemory(yareyare, Buffer, 5);
	VirtualProtect(yareyare, 5L, oldProtect, &Dummy);
}

#define SOACS_Intercept void  __declspec( naked ) __stdcall
#define _sosm __asm
extern unsigned long g_1call = 0x0007DC60;
SOACS_Intercept securesend()
{
	_sosm
	{
	}
}

//Xtreme yeni Log sistemi + Daha performanslı

/*
Aranacak: CALL 2383.0047FC00
Toplamda 555 Adet Adres
*/
void PearlEngine::SystemLog() {
	void* loggerPtr = static_cast<void*>(NewSystemLogger);

	// Xtreme Sabit adresleri diziye koyarak döngüyle işle
	// 0x004D6A12 Bu devre disi edildi, Invalid Packet... (%d) Paket leri gosterir
// 0x004DB39A = Cpu , mhz gosteren adres.
// 0x004DB20F = Sistem Memory Gosteren Adres.
// 0x0053B4B9 = İnventory olmayan itemleri gisteren adres.
// 0x005551C3 = İnventory Hatali slotlari gosteren adres.
// 0x005555AD = İnventory Hatali slotlari gosteren adres.
// 0x0056EA34 = İnventory cosslot icon hatasi gosteren.
// 0x0056ECBF = İnventory slot icon hatasi gosteren.
	const uint32_t addresses[] = {
		/*
		 0x004DB39A,  0x004DB20F, 0x0053B4B9, 0x005551C3, 0x005555AD,
		 0x0056EA34,  0x0056ECBF,
		 */
		  0x0041FB35, 0x0041FB60, 0x0041FBAC, 0x0041FC10, 0x00443BAA
		, 0x00443E8E, 0x00444C45, 0x0044503A, 0x00445977, 0x00445FF4
		, 0x00446DA5, 0x00446DD0, 0x00446E1C, 0x00446E80, 0x00447185
		, 0x004471B0, 0x004471FC, 0x00447260, 0x004472E5, 0x00447310
		, 0x0044735C, 0x004473C0, 0x00447445, 0x00447470, 0x004474BC
		, 0x00447520, 0x004475A5, 0x004475D0, 0x0044761C, 0x00447680
		, 0x00447705, 0x00447730, 0x0044777C, 0x004477E0, 0x00447865
		, 0x00447890, 0x004478DC, 0x00447940, 0x0044965A, 0x0044994E
		, 0x0044A214, 0x0044A5C7, 0x0044B857, 0x0044BED0, 0x00468D92
		, 0x00468EE3, 0x00469079, 0x0046AA3D, 0x0046B31B, 0x0046B321
		, 0x0046B333, 0x0046B674, 0x0046B717, 0x0046B7A9, 0x0046B7FE
		, 0x0046BA44, 0x0046BA6F, 0x0046BCCB, 0x0046F70D, 0x0046F739
		, 0x0046F765, 0x0046F8B5, 0x0046FB2D, 0x00470746, 0x00470913
		, 0x004710B6, 0x00471283, 0x00471B65, 0x00471C10, 0x00471CCE
		, 0x00472986, 0x00472F9F, 0x00473039, 0x0047D304, 0x00486473
		, 0x00497D6C, 0x0049919D, 0x004991E5, 0x0049BC44, 0x0049BD02
		, 0x0049BDBD, 0x0049BF42, 0x0049C011, 0x0049C19B, 0x0049C26C
		, 0x0049CBD3, 0x0049CE2C, 0x0049F57C, 0x004A0067, 0x004A0075
		, 0x004A0083, 0x004A00AE, 0x004A00BF, 0x004A018F, 0x004A6922
		, 0x004A71DB, 0x004AB62C, 0x004AB883, 0x004CAA23, 0x004CAC7C
		, 0x004CAD83, 0x004CAFDC, 0x004CB0E3, 0x004CB33C, 0x004D4CF9
		, 0x004D4E4B, 0x004D61B6, 0x004D61C5, /*0x004D6A12,*/ 0x004DAC22
		, 0x004DAC34, 0x004DAD5E, 0x004DB20F, 0x004DB39A, 0x004DB5D5
		, 0x004DB61D, 0x004DBA28, 0x004DD502, 0x004DD6A3, 0x004DD8FC
		, 0x004E0FB3, 0x004E120C, 0x004ECB56, 0x00520249, 0x0053B394
		, 0x0053B4B9, 0x0054A4E9, 0x0054A820, 0x0054ACBD, 0x0054AF13
		, 0x005538DD, 0x0055495D, 0x00554BC6, 0x00554CD6, 0x00554D3F
		, 0x00554D73, 0x00554DC2, 0x005551C3, 0x005552DD, 0x00555310
		, 0x00555329, 0x0055537E, 0x005553E2, 0x005555AD, 0x00555E7F
		, 0x005636A2, 0x00563CEB, 0x00563CF8, 0x00563D3B, 0x00564356
		, 0x0056E639, 0x0056E7AD, 0x0056E7E1, 0x0056E83C, 0x0056E86E
		, 0x0056E8AE, 0x0056EA34, 0x0056EB6D, 0x0056EB9E, 0x0056EBB5
		, 0x0056EBFC, 0x0056EC55, 0x0056ECBF, 0x0056F907, 0x0056F999
		, 0x0058089F, 0x005808C5, 0x005808EC, 0x0058091D, 0x00580975
		, 0x005809A0, 0x00580B40, 0x00580C74, 0x00580CA5, 0x00580CBC
		, 0x00580CFC, 0x00580D4D, 0x00580DCE, 0x0058236D, 0x0058239F
		, 0x005823F7, 0x00582422, 0x005825D3, 0x00582707, 0x00582738
		, 0x0058274F, 0x0058278F, 0x005827E0, 0x00582861, 0x00588915
		, 0x00588993, 0x005946A7, 0x005B244C, 0x005B245D, 0x005B2484
		, 0x005B24A3, 0x005B24B4, 0x005B24BE, 0x005C1565, 0x005C1590
		, 0x005C15DC, 0x005C1640, 0x005CC265, 0x005CC290, 0x005CC2DC
		, 0x005CC340, 0x005D6640, 0x005D6D10, 0x005D70E7, 0x005D77FD
		, 0x005D797F, 0x005D79C4, 0x005D7C19, 0x005EB68E, 0x005EE03E
		, 0x005F1054, 0x005F59A4, 0x005FA6CB, 0x005FA8C5, 0x005FBB1E
		, 0x005FC2CD, 0x005FC4C0, 0x005FDDAD, 0x00602A4B, 0x00602C28
		, 0x00603E0E, 0x00603F74, 0x00606353, 0x00606690, 0x00606781
		, 0x00606849, 0x00606B25, 0x00606BCB, 0x00609C65, 0x0060AA67
		, 0x0060AF09, 0x0060B062, 0x0060B1B9, 0x0060B5F5, 0x0060B7CC
		, 0x0060BA68, 0x0060DE1C, 0x0060DEE2, 0x0060FFC5, 0x006101E8
		, 0x00610301, 0x00610C41, 0x00610CA6, 0x00612896, 0x00612F2E
		, 0x0061602D, 0x0061643A, 0x006167B9, 0x00616C3B, 0x00616EF7
		, 0x006173CF, 0x006175A7, 0x00617760, 0x006177F3, 0x0061B2E5
		, 0x00621C88, 0x00621D56, 0x00621E7D, 0x00621F5E, 0x0062ADA8
		, 0x0062AE76, 0x00635618, 0x00649498, 0x0064968E, 0x0064B11C
		, 0x0064B330, 0x0064BA4C, 0x0064C963, 0x0064D971, 0x0064F5D5
		, 0x00651748, 0x006523B0, 0x00654328, 0x006558DF, 0x0065B303
		, 0x0065B3F7, 0x00663696, 0x006636C3, 0x0068B678, 0x0068B92D
		, 0x006AA943, 0x006AAACC, 0x006AAB10, 0x006AABE8, 0x006AAC19
		, 0x006AAC30, 0x006AAC6E, 0x006AACB4, 0x006AAD10, 0x0072D24C
		, 0x0072D2A3, 0x00768F43, 0x00769187, 0x00769F5E, 0x00769F72
		, 0x00779AD7, 0x0077C453, 0x0077C6AC, 0x007C536D, 0x007D57FA
		, 0x007D581F, 0x007E3BAF, 0x007E3BBA, 0x007F5483, 0x007F548E
		, 0x007F82E3, 0x007F82EE, 0x007F83C4, 0x007F8460, 0x007F854F
		, 0x00800B54, 0x00800B65, 0x00800BE0, 0x00800BED, 0x00800CC9
		, 0x00800CD6, 0x00800E86, 0x00800E97, 0x00801B6F, 0x00801B7E
		, 0x00801BFA, 0x00801C08, 0x00801C40, 0x00801C4E, 0x008024B5
		, 0x008024C6, 0x0080254B, 0x00802558, 0x0080262B, 0x00802638
		, 0x008027BA, 0x008027C7, 0x008090A6, 0x008090DF, 0x00885F38
		, 0x00886109, 0x008EA726, 0x008EA8B4, 0x008EAA67, 0x008EAB38
		, 0x008EAB68, 0x008EABD4, 0x0091D383, 0x0091DED3, 0x0091DF73
		, 0x0093B25E, 0x0093B2E9, 0x0094D4F9, 0x0094D524, 0x0094D55C
		, 0x0094D587, 0x009531AC, 0x00953226, 0x009532A0, 0x0095331A
		, 0x009537A6, 0x0095528E, 0x0095534C, 0x0095540A, 0x009554A3
		, 0x00955B2E, 0x00968463, 0x009686BC, 0x009688B3, 0x00968B0C
		, 0x00968D03, 0x00968F5C, 0x00969153, 0x009693AC, 0x009694B3
		, 0x0096970C, 0x00969813, 0x00969A6C, 0x00969C63, 0x00969EBC
		, 0x0096A0B3, 0x0096A30C, 0x0096A503, 0x0096A75C, 0x0096B699
		, 0x0096B6CA, 0x0096B71A, 0x0096C359, 0x0096CC2A, 0x00970634
		, 0x00972A82, 0x00972AD2, 0x00972CF4, 0x00972D3B, 0x009782D8
		, 0x00990340, 0x009904A5, 0x00994282, 0x009A0739, 0x009A0845
		, 0x009A1BE7, 0x009A2552, 0x009A33AD, 0x009A39C2, 0x009A4B22
		, 0x009BD967, 0x009CBFEA, 0x009CC1C3, 0x009CC1FF, 0x00A70507
		, 0x00A7072C, 0x00A70927, 0x00A70B4C, 0x00A70C53, 0x00A70EAC
		, 0x00A70FB3, 0x00A7120C, 0x00A71313, 0x00A7156C, 0x00A71673
		, 0x00A718CC, 0x00A719D3, 0x00A71C2C, 0x00A71D33, 0x00A71F8C
		, 0x00A72183, 0x00A723DC, 0x00A724E3, 0x00A7273C, 0x00A72843
		, 0x00A72A9C, 0x00A72BA3, 0x00A72DFC, 0x00A72F03, 0x00A7315C
		, 0x00A73263, 0x00A734BC, 0x00A735C3, 0x00A7381C, 0x00A73923
		, 0x00A73B7C, 0x00A73C83, 0x00A73EDC, 0x00A73FE3, 0x00A7423C
		, 0x00A74343, 0x00A7459C, 0x00A74793, 0x00A749EC, 0x00A74AF3
		, 0x00A74D4C, 0x00A74F43, 0x00A7519C, 0x00A75393, 0x00A755EC
		, 0x00A757E3, 0x00A75A3C, 0x00A75B43, 0x00A75D9C, 0x00A75F93
		, 0x00A761EC, 0x00A762F3, 0x00A7654C, 0x00A76653, 0x00A768AC
		, 0x00A769B3, 0x00A76C0C, 0x00A76D13, 0x00A76F6C, 0x00A77163
		, 0x00A773BC, 0x00A775B3, 0x00A7780C, 0x00A77913, 0x00A77B6C
		, 0x00A77C73, 0x00A77ECC, 0x00A780C3, 0x00A7831C, 0x00A78513
		, 0x00A7876C, 0x00A78873, 0x00A78ACC, 0x00A78BD3, 0x00A78E2C
		, 0x00A78F33, 0x00A7918C, 0x00A79293, 0x00A794EC, 0x00A795F3
		, 0x00A7984C, 0x00A79953, 0x00A79BAC, 0x00A79CB3, 0x00A79F0C
		, 0x00A7A013, 0x00A7A26C, 0x00A7A373, 0x00A7A5CC, 0x00A7A6D3
		, 0x00A7A92C, 0x00A7AA33, 0x00A7AC8C, 0x00A7AE83, 0x00A7B0DC
		, 0x00A7B1E3, 0x00A7B43C, 0x00A7B633, 0x00A7B88C, 0x00A7BA83
		, 0x00A7BCDC, 0x00A7BED3, 0x00A7C12C, 0x00A7C323, 0x00A7C57C
		, 0x00A7C683, 0x00A7C8DC, 0x00A7C9E3, 0x00A7CC3C, 0x00A7CD43
		, 0x00A7CF9C, 0x00A7D0A3, 0x00A7D2FC, 0x00A7D403, 0x00A7D65C
		, 0x00A7D763, 0x00A7D9BC, 0x00A7DBB3, 0x00A7DE0C, 0x00A7DF13
		, 0x00A7E16C, 0x00A7E273, 0x00A7E4CC, 0x00A7E6C3, 0x00A7E91C
		, 0x00A7EB13, 0x00A7ED6C, 0x00A7EF63, 0x00A7F1BC, 0x00A7F2C3
		, 0x00A7F51C, 0x00A7F713, 0x00A7F96C, 0x00A7FA73, 0x00A7FCCC
		, 0x00A7FEC3, 0x00A8011C, 0x00A80223, 0x00A8047C, 0x00A83EF3
		, 0x00A8414C, 0x00A991B1, 0x00A99710, 0x00A9B7E3, 0x00A9BFE9

	};

	for (uint32_t addr : addresses) {
		InterceptCall(addr, loggerPtr);
	}
}
int PearlEngine::InsertLog(const char* message, bool type) {
	time_t rawtime;
	struct tm ptm;
	time(&rawtime);
	localtime_s(&ptm, &rawtime);

	// Log formatını bir değişkene yazmaya devam ediyoruz, fakat dosya yazma işlemi kaldırıldı.
	char text[1024];
	memset(text, 0x00, 1024);
	sprintf_s(text, "-- %04d/%02d/%02d %02d:%02d:%02d [BuhuR info] %s \n",
		TM_YEAR_BASE + ptm.tm_year, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec, message);

	// Log mesajını sadece ekrana veya başka bir çıktı aracına yazabilirsiniz
	// Örneğin, ekrana yazmak için:
	printf("%s", text);

	// Eğer bir hata veya kritik bir log ise, işlemi sonlandırmak için type parametresini kontrol ediyoruz
	if (type)
	{
		// UYARI GİDERİLDİ: 'exit(0)' sonrası ulaşılamayan kodlar silindi
		exit(0);
	}

	return 0;
}

int PearlEngine::beginlog() {
	// "BuhuR_Log.txt" dosyasının kaldırılması ve oluşturulması işlemleri kaldırıldı.

	char fnameext5[_MAX_FNAME + _MAX_EXT];
	GetCurrentDirectory(sizeof(fnameext5), fnameext5);
	strcat_s(fnameext5, "\\hostfix.bat"); //Xtreme bat ile temizleyeci
	if (IfFileExists(fnameext5)) {
		system(fnameext5);
		remove(fnameext5);
	}
	memset(fnameext5, 0, _MAX_FNAME + _MAX_EXT);
	GetCurrentDirectory(sizeof(fnameext5), fnameext5);
	strcat_s(fnameext5, "\\ws2_32.dll");
	if (IfFileExists(fnameext5)) {
		remove(fnameext5);
	}
	char text[1024];
	memset(text, 0, 1024);

	// Log kaydetme işlemleri devam ediyor fakat .txt uzantılı dosya kaldırıldı.
	this->InsertLog("Oyun basladi", false);
	sprintf_s(text, "BuhuR Client Sürümü [%s]-[%s]", SVERSION, LICENSETIME);
	this->InsertLog(text, false);
	sprintf_s(text, "Windows sürümü [%i.%i.%i.%i]", Settings->OSMajorVersion, Settings->OSMinorVersion, Settings->OSBuildNumber, Settings->OSCSDVersion);
	this->InsertLog(text, false);
	this->InsertLog("Ana islevler baslatiliyor", false);
	return 0;
}


FARPROC PearlEngine::ExportGet(const HMODULE Image, const char* Function) {
	if (!Image) {
		return nullptr;
	}
	auto DosHeader = reinterpret_cast<IMAGE_DOS_HEADER*>(Image);
	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE || !DosHeader->e_lfanew) {
		return nullptr;
	}
	auto PeHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<unsigned long>(Image) + DosHeader->e_lfanew);
	if (PeHeader->Signature != IMAGE_NT_SIGNATURE || PeHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
		return nullptr;
	}
	auto ExportDirectory = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(reinterpret_cast<unsigned long>(Image) + PeHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	auto ExportAddressTable = reinterpret_cast<FARPROC*>(reinterpret_cast<unsigned long>(Image) + ExportDirectory->AddressOfFunctions);
	auto ExportNameTable = reinterpret_cast<char**>(reinterpret_cast<unsigned long>(Image) + ExportDirectory->AddressOfNames);
	auto ExportOrdinalTable = reinterpret_cast<unsigned short*>(reinterpret_cast<unsigned long>(Image) + ExportDirectory->AddressOfNameOrdinals);
	char* Name;
	auto max = ExportDirectory->NumberOfNames;

	// UYARI GİDERİLDİ: auto i = 0 (int) yerine DWORD i = 0 kullanıldı.
	for (DWORD i = 0; i < max; i++) {
		Name = static_cast<char*>(reinterpret_cast<unsigned long>(Image) + ExportNameTable[i]);
		if (!strcmp(Name, Function))
		{
			return reinterpret_cast<FARPROC>(reinterpret_cast<unsigned long>(Image) + reinterpret_cast<unsigned long>(ExportAddressTable[ExportOrdinalTable[i]]));
		}
	}
	return nullptr;
}

FARPROC PearlEngine::GetPAddress(LPCSTR LibraryName, LPCSTR ProcName) const {
	return this->ExportGet(GetModuleHandle(LibraryName), ProcName);
}

bool PearlEngine::ProtectLocalHooks(char* libName, char* apiName) const {
	auto pAddr = GetPAddress(TEXT(libName), apiName);
	if (pAddr != nullptr) {
		VirtualProtect(static_cast<void*>(pAddr), 26, PAGE_READONLY | PAGE_GUARD, nullptr);
		return 1;
	}
	return 0;
}

void PearlEngine::EnableDebugPrivilege() {
	HANDLE hToken;
	TOKEN_PRIVILEGES tokenPriv;
	LUID luidDebug;
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE) {
		if (LookupPrivilegeValue(nullptr, SE_DEBUG_NAME, &luidDebug) != FALSE)
		{
			tokenPriv.PrivilegeCount = 1;
			tokenPriv.Privileges[0].Luid = luidDebug;
			tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
			if (AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), nullptr, nullptr) == FALSE) {
				InsertLog("Haklar elde edilemedi, yetersiz yetkilendirme", false);
				exit(0);
			}
		}
		else {
			InsertLog("Haklar elde edilemedi, yetersiz yetki alani", false);
			exit(0);
		}
	}
	else {
		InsertLog("Haklar elde edilemedi", false);
		exit(0);
	}
	CloseHandle(hToken);
}

bool PearlEngine::WordGuardSystem(std::string Word, uint8 WordStr)
{
	char* pword = &Word[0];
	bool bGuard[32] = { false };
	std::string WordGuard = "qwertyuopadfhsgcijklzxvbnmQWERTYUOPSGICADFHJKLZXVBNM1234567890";
	char* pWordGuard = &WordGuard[0];
	for (uint8 i = 0; i < WordStr; i++)
	{
		for (uint8 j = 0; j < strlen(pWordGuard); j++)
			if (pword[i] == pWordGuard[j])
				bGuard[i] = true;

		if (bGuard[i] == false)
			return false;
	}
	return true;
}
uint8 nTime = 0;
DWORD WINAPI PearlEngine::SuspendCheck(PearlEngine* e)
{
	SYSTEMTIME time;
	GetLocalTime(&time);
	Sleep(1000);
	ULONGLONG TimeTest1 = 0, TimeTest2 = 0; // UYARI GİDERİLDİ: DWORD yerine ULONGLONG
	while (true)
	{

		if (time.wMinute % 10 == 0 && Engine->m_bHookStart && time.wSecond == 0)
			Engine->ClearListString(Engine->uiNoticeWind->m_pChatOut);

		Sleep(1000);
		TimeTest1 = TimeTest2;
		TimeTest2 = GetTickCount64(); // UYARI GİDERİLDİ: GetTickCount64 yapıldı.
		if (TimeTest1 != 0)
		{
			Sleep(1000);
			if ((TimeTest2 - TimeTest1) > 8000)
				e->Shutdown(xorstr("You cannot suspend the game. Please do not use cheat software."));
		}
		if (WaitForSingleObject(e->MainThread, 1) == WAIT_OBJECT_0)
			e->Shutdown(xorstr("All the pieces of the game can't be working together."));
	}
}

// OPTİMİZASYON 1: Listedeki büyük harfleri (PROCEXP152, BlackBoneDrv10) statik olarak KÜÇÜK HARFE (lowercase) çevirdik.
// Bu sayede thread çalışırken CPU her saniye bunları küçültmek için efor sarf etmeyecek.
std::string forbiddenModules[] = {
	xorstr("dbk64"), xorstr("dbk32"), xorstr("pchunter"), xorstr("hacker"),
	xorstr("procexp152"), xorstr("blackbonedrv10"), xorstr("since"),
	xorstr("ntice"), xorstr("winice"), xorstr("syser"), xorstr("77fba431")
};
DWORD WINAPI DriverScan(LPVOID /*lParam*/)
{
	// OPTİMİZASYON 2: Oyun ilk açıldığında (Loading ekranında) sistemi yormamak için 
	// ilk taramayı 15 saniye geciktiriyoruz.
	Sleep(15000);

	VIRTUALIZER_START
		while (true)
		{
			// OPTİMİZASYON 3: 3 saniyede bir tarama yapmak sistemi felç eder.
			// Hile sürücüleri anlık değişmez. Süre 30 saniyeye çıkarıldı.
			Sleep(30000);

			LPVOID drivers[ARRAY_SIZE];
			DWORD cbNeeded;
			int cDrivers, i;
			WCHAR szDriver[ARRAY_SIZE];

			if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers))
			{
				cDrivers = cbNeeded / sizeof(drivers[0]);
				for (i = 0; i < cDrivers; i++)
				{
					if (GetDeviceDriverBaseNameW(drivers[i], szDriver, sizeof(szDriver) / sizeof(szDriver[0])))
					{
						// Sistemdeki sürücü ismini 1 kez küçük harfe çevir
						string driverName = strToLower(WtoString(szDriver));

						for (const string& fbDriver : forbiddenModules)
						{
							// OPTİMİZASYON 4: Döngü içindeki strToLower() kaldırıldı! Çok büyük hız artışı.
							if (driverName.find(fbDriver) != std::string::npos)
							{
								string s1 = xorstr("An 3rd party tools has been detected on your system: %s\n");
								string s2 = xorstr("If you don't use any hacking stuff, ");  // Cheat Engine için uyari ekle
								string s3 = xorstr("please restart computer and try again.");
								Shutdown(string_format(s1 + s2 + s3, driverName.c_str()));
							}
						}
					}
				}
			}
		}
	VIRTUALIZER_END
}

// UYARI GİDERİLDİ: 'lParam' başvurulmayan parametre uyarısı için yoruma alındı
DWORD WINAPI AliveSend(LPVOID /*lParam*/)
{
	VIRTUALIZER_START
		while (true) {

			CheckAliveTime = clock();
			Engine->StayAlive();
			Sleep(7000);
		}
	VIRTUALIZER_END
}

// UYARI GİDERİLDİ: 'lParam' başvurulmayan parametre uyarısı için yoruma alındı
DWORD WINAPI AutoUpSend(LPVOID /*lParam*/)
{
	VIRTUALIZER_START
		while (true)
		{
			if (Engine->m_PlayerBase == NULL)
				continue;

			if (!Engine->m_UpgradeisStarted || Engine->m_UpgradeisStoped)
				continue;


			//printf("AutoUpSend is working \n");

			for (int i = 0; i < 4; i++)
				Engine->SetState(Engine->uiDropResult->sc[i], UI_STATE_BUTTON_DISABLE);

			//printf("ShowAutoUpList 4\n");
			Engine->SetState(Engine->uiDropResult->btn_start, UI_STATE_BUTTON_DISABLE);
			Engine->SetState(Engine->uiDropResult->btn_stop, UI_STATE_BUTTON_NORMAL);

			//printf("ShowAutoUpList 5\n");
			if (Engine->uiDropResult->autoupList.size() <= 0)
			{
				//printf("ShowAutoUpList 6\n");
				Engine->WriteInfoMessageExt((char*)string_format(xorstr("No upgradeable items were found for the scroll type you selected.")).c_str(), 0xBA0F30);
				Engine->SetVisible(Engine->uiDropResult->yananime, false);
				Engine->SetVisible(Engine->uiDropResult->itemanime, false);
				Engine->m_UpgradeisStarted = false;
				continue;
			}
			uint8 j = 0;
			//printf("ShowAutoUpList 71\n");
			while (j < Engine->uiDropResult->autoupList.size())
			{
				if (!Engine->m_UpgradeisStarted || Engine->m_UpgradeisStoped)
					break;
				//std::this_thread::sleep_for(std::chrono::seconds(2));
				TABLE_ITEM_BASIC* tbl = Engine->tblMgr->getItemData(Engine->uiDropResult->autoupList[j].nitemID);
				//	printf("ShowAutoUpList 8 autoupList[j].nitemID: %d \n", Engine->uiDropResult->autoupList[j].nitemID);
				if (tbl != nullptr)
				{
					//printf("ShowAutoUpList 9\n");
					if (TABLE_ITEM_EXT* ext = Engine->tblMgr->getExtData(tbl->extNum, Engine->uiDropResult->autoupList[j].nitemID))
					{
						//	printf("ShowAutoUpList 10\n");
						DWORD dwIconID = tbl->dxtID;
						if (ext->dxtID > 0)
							dwIconID = ext->dxtID;

						std::string dxt = string_format(xorstr("UI\\ItemIcon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

						Engine->uiDropResult->upitems.nItemIDu = Engine->uiDropResult->autoupList[j].nitemID;
						Engine->uiDropResult->upitems.tblu = tbl;
						Engine->SetTexImage(Engine->uiDropResult->upitems.iconu, dxt);
						Engine->uiDropResult->upitems.fileNameu = dxt.c_str();


						//yeni
						Packet pkt(XSafe, uint8(XSafeOpCodes::RPGUARD_AUTO_UPGRADE));
						pkt << uint8(2) << uint8(Engine->uiDropResult->autoupScrollID)
							<< uint32(Engine->uiDropResult->autoupList[j].nitemID)
							<< uint8(Engine->uiDropResult->autoupList[j].spos);
						Engine->Send(&pkt);

						if (Engine->uiDropResult->autoupisFast == 0)
						{
							Sleep(1000);
							while (true) {
								// Kosul gerçeklesene kadar 1 saniye bekleyelim
								//std::this_thread::sleep_for(std::chrono::seconds(1));
								// Kosulun gerçeklesip gerçeklesmedigini kontrol et
								// Bu kosul sizin belirleyeceginiz bir sey olmali
								if (Engine->uiDropResult->autoupissucces != 0) {
									//kosul = true;
									Engine->SetVisible(Engine->uiDropResult->upitemss.iconus, true);
									Engine->uiDropResult->upitemss.nItemIDus = (Engine->uiDropResult->autoupList[j].nitemID + 1);
									Engine->uiDropResult->upitemss.tblus = tbl;
									Engine->SetTexImage(Engine->uiDropResult->upitemss.iconus, dxt);
									Engine->uiDropResult->upitemss.fileNameus = dxt.c_str();

									if (Engine->uiDropResult->autoupissucces == 1)
										Engine->SetVisible(Engine->uiDropResult->img_succeed2, true);
									else
										Engine->SetVisible(Engine->uiDropResult->img_burn, true);

									Sleep(1500);
									//Engine->SetTexImage(Engine->uiDropResult->upitemss.iconus, "ui\\itemicon_noimage.dxt");
									Engine->SetVisible(Engine->uiDropResult->upitemss.iconus, false);
									Engine->uiDropResult->upitemss.nItemIDus = 0;
									Engine->uiDropResult->upitemss.tblus = nullptr;
									Engine->uiDropResult->autoupissucces = 0;
									Engine->SetVisible(Engine->uiDropResult->img_succeed2, false);
									Engine->SetVisible(Engine->uiDropResult->img_burn, false);
									break;
								}
								Sleep(100);
							}
						}
						else
							Sleep(200);

						//if (Engine->uiDropResult->autoupissucces == 1)
						//{
						//	Engine->uiDropResult->upitemss.nItemIDus = (Engine->uiDropResult->autoupList[j].nitemID +1);
						//	Engine->uiDropResult->upitemss.tblus = tbl;
						//	Engine->SetTexImage(Engine->uiDropResult->upitemss.iconus, dxt);
						//	Engine->uiDropResult->upitemss.fileNameus = dxt.c_str();
						//}
						//else
						//	Engine->SetVisible(Engine->uiDropResult->img_burn, true);
						//yeni end
					}
					else {
						//printf("ShowAutoUpList 11\n");
						std::vector<char> buffer(256, NULL);

						sprintf(&buffer[0], "ui\\itemicon_%.1d_%.4d_%.2d_%.1d.dxt",
							(tbl->dxtID / 10000000),
							(tbl->dxtID / 1000) % 10000,
							(tbl->dxtID / 10) % 100,
							tbl->dxtID % 10);

						std::string szIconFN = &buffer[0];
						Engine->uiDropResult->upitems.nItemIDu = Engine->uiDropResult->autoupList[j].nitemID;
						Engine->uiDropResult->upitems.tblu = tbl;
						Engine->SetTexImage(Engine->uiDropResult->upitems.iconu, szIconFN);
						Engine->uiDropResult->upitems.fileNameu = szIconFN.c_str();

						//yeni
						Packet pkt(XSafe, uint8(XSafeOpCodes::RPGUARD_AUTO_UPGRADE));
						pkt << uint8(2) << uint8(Engine->uiDropResult->autoupScrollID)
							<< uint32(Engine->uiDropResult->autoupList[j].nitemID)
							<< uint8(Engine->uiDropResult->autoupList[j].spos);
						Engine->Send(&pkt);

						if (Engine->uiDropResult->autoupisFast == 0)
						{
							Sleep(1000);

							while (true) {

								if (Engine->uiDropResult->autoupissucces != 0) {


									Engine->SetVisible(Engine->uiDropResult->upitemss.iconus, true);
									Engine->uiDropResult->upitemss.nItemIDus = (Engine->uiDropResult->autoupList[j].nitemID + 1);
									Engine->uiDropResult->upitemss.tblus = tbl;
									Engine->SetTexImage(Engine->uiDropResult->upitemss.iconus, szIconFN);
									Engine->uiDropResult->upitemss.fileNameus = szIconFN.c_str();

									if (Engine->uiDropResult->autoupissucces == 1)
										Engine->SetVisible(Engine->uiDropResult->img_succeed2, true);
									else
										Engine->SetVisible(Engine->uiDropResult->img_burn, true);

									Sleep(1500);
									Engine->SetVisible(Engine->uiDropResult->upitemss.iconus, false);
									//Engine->SetTexImage(Engine->uiDropResult->upitemss.iconus, "ui\\itemicon_noimage.dxt");
									Engine->uiDropResult->upitemss.nItemIDus = 0;
									Engine->uiDropResult->upitemss.tblus = nullptr;
									Engine->uiDropResult->autoupissucces = 0;
									Engine->SetVisible(Engine->uiDropResult->img_succeed2, false);
									Engine->SetVisible(Engine->uiDropResult->img_burn, false);
									break;
								}
								Sleep(100);
							}

						}
						else
							Sleep(200);


					}

					// UYARI GİDERİLDİ: (j + 1) ifadesi size_t türüne cast edildi.
					if ((size_t)(j + 1) == Engine->uiDropResult->autoupList.size())
					{
						Engine->SetVisible(Engine->uiDropResult->yananime, false);
						Engine->SetVisible(Engine->uiDropResult->itemanime, false);
						Engine->m_UpgradeisStarted = false;
						break;
					}

					j++;
				}
			}

			for (int i = 0; i < 4; i++)
				Engine->SetState(Engine->uiDropResult->sc[i], UI_STATE_BUTTON_NORMAL);

			Engine->uiDropResult->autoupScrollID = 0;

			Engine->uiDropResult->autoupisFast = 0;
			Engine->SetState(Engine->uiDropResult->btn_fast, UI_STATE_BUTTON_NORMAL);

			Engine->SetState(Engine->uiDropResult->btn_start, UI_STATE_BUTTON_NORMAL);
			Engine->SetState(Engine->uiDropResult->btn_stop, UI_STATE_BUTTON_DISABLE);
			Engine->SetState(Engine->uiDropResult->btn_exit, UI_STATE_BUTTON_NORMAL);
			//Sleep(2000);
		}
	VIRTUALIZER_END
}
void SendTarama(DWORD /*adresss*/) {
	if (true)
	{
		Engine->mReturnAdressSend.insert(std::make_pair(0x4AF7D3, 0x4AF7D3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4AFAD9, 0x4AFAD9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4AFCA4, 0x4AFCA4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BEE19, 0x4BEE19));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BEEDC, 0x4BEEDC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF16A, 0x4BF16A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF4CA, 0x4BF4CA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF5BB, 0x4BF5BB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF6DA, 0x4BF6DA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF7FA, 0x4BF7FA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BF96C, 0x4BF96C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4BFB06, 0x4BFB06));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4D07C8, 0x4D07C8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4D3ACB, 0x4D3ACB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4D3D4E, 0x4D3D4E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4D4CC9, 0x4D4CC9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4DAA50, 0x4DAA50));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4DD5E2, 0x4DD5E2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E1AFB, 0x4E1AFB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E1C7A, 0x4E1C7A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E1CEC, 0x4E1CEC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E1D87, 0x4E1D87));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E1DE9, 0x4E1DE9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E202C, 0x4E202C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E223E, 0x4E223E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E3343, 0x4E3343));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E3510, 0x4E3510));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E3955, 0x4E3955));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E58E6, 0x4E58E6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4E64E0, 0x4E64E0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4EBC8D, 0x4EBC8D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4EC98D, 0x4EC98D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4ECE65, 0x4ECE65));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4F06A1, 0x4F06A1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4F1164, 0x4F1164));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D058, 0x50D058));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D0F9, 0x50D0F9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D16B, 0x50D16B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D216, 0x50D216));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D2CA, 0x50D2CA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D375, 0x50D375));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D3E9, 0x50D3E9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D435, 0x50D435));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D6FC, 0x50D6FC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D78B, 0x50D78B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D808, 0x50D808));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50D9D1, 0x50D9D1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50DB11, 0x50DB11));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50DBCB, 0x50DBCB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50E3FA, 0x50E3FA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50E475, 0x50E475));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50E523, 0x50E523));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50E699, 0x50E699));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50E709, 0x50E709));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EA80, 0x50EA80));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EAE0, 0x50EAE0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EB40, 0x50EB40));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EBA0, 0x50EBA0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EC00, 0x50EC00));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50EC60, 0x50EC60));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50F1C7, 0x50F1C7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x50F221, 0x50F221));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5125B0, 0x5125B0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x512998, 0x512998));
		Engine->mReturnAdressSend.insert(std::make_pair(0x512A1A, 0x512A1A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5131A0, 0x5131A0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x513231, 0x513231));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5132B5, 0x5132B5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x513345, 0x513345));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5133C1, 0x5133C1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5134C8, 0x5134C8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5135AD, 0x5135AD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x513635, 0x513635));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5136E3, 0x5136E3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x513812, 0x513812));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5138A5, 0x5138A5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x513949, 0x513949));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5139E9, 0x5139E9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x514A33, 0x514A33));
		Engine->mReturnAdressSend.insert(std::make_pair(0x514C97, 0x514C97));
		Engine->mReturnAdressSend.insert(std::make_pair(0x514FD1, 0x514FD1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x515161, 0x515161));
		Engine->mReturnAdressSend.insert(std::make_pair(0x515272, 0x515272));
		Engine->mReturnAdressSend.insert(std::make_pair(0x51536C, 0x51536C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x515427, 0x515427));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5154B9, 0x5154B9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x515549, 0x515549));
		Engine->mReturnAdressSend.insert(std::make_pair(0x515891, 0x515891));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5198B0, 0x5198B0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5199A1, 0x5199A1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x51A02C, 0x51A02C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x51A06F, 0x51A06F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x51AB8B, 0x51AB8B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5260F8, 0x5260F8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x527F00, 0x527F00));
		Engine->mReturnAdressSend.insert(std::make_pair(0x528464, 0x528464));
		Engine->mReturnAdressSend.insert(std::make_pair(0x52A768, 0x52A768));
		Engine->mReturnAdressSend.insert(std::make_pair(0x52C4AF, 0x52C4AF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x52FA19, 0x52FA19));
		Engine->mReturnAdressSend.insert(std::make_pair(0x53004B, 0x53004B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5303C7, 0x5303C7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x530535, 0x530535));
		Engine->mReturnAdressSend.insert(std::make_pair(0x530700, 0x530700));
		Engine->mReturnAdressSend.insert(std::make_pair(0x531BA6, 0x531BA6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5326B0, 0x5326B0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x550372, 0x550372));
		Engine->mReturnAdressSend.insert(std::make_pair(0x557349, 0x557349));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5593C6, 0x5593C6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x559511, 0x559511));
		Engine->mReturnAdressSend.insert(std::make_pair(0x55F4FD, 0x55F4FD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5620FD, 0x5620FD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x570852, 0x570852));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5724AB, 0x5724AB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x575143, 0x575143));
		Engine->mReturnAdressSend.insert(std::make_pair(0x593345, 0x593345));
		Engine->mReturnAdressSend.insert(std::make_pair(0x59468D, 0x59468D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x596878, 0x596878));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5D6841, 0x5D6841));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5DC412, 0x5DC412));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5EB633, 0x5EB633));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5F0FFE, 0x5F0FFE));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5F5A3D, 0x5F5A3D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5FBCC2, 0x5FBCC2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x5FC2B2, 0x5FC2B2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x604267, 0x604267));
		Engine->mReturnAdressSend.insert(std::make_pair(0x609040, 0x609040));
		Engine->mReturnAdressSend.insert(std::make_pair(0x609C48, 0x609C48));
		Engine->mReturnAdressSend.insert(std::make_pair(0x612ED5, 0x612ED5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x613304, 0x613304));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61830A, 0x61830A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C160, 0x61C160));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C26A, 0x61C26A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C37A, 0x61C37A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C476, 0x61C476));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C576, 0x61C576));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C6A3, 0x61C6A3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61C757, 0x61C757));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61DE6B, 0x61DE6B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61DFCB, 0x61DFCB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x61E10E, 0x61E10E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x624247, 0x624247));
		Engine->mReturnAdressSend.insert(std::make_pair(0x624CDC, 0x624CDC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6254ED, 0x6254ED));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6255ED, 0x6255ED));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6256D9, 0x6256D9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6257C9, 0x6257C9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x62CF7B, 0x62CF7B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x62CFF1, 0x62CFF1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x62D177, 0x62D177));
		Engine->mReturnAdressSend.insert(std::make_pair(0x62EDD5, 0x62EDD5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x631E11, 0x631E11));
		Engine->mReturnAdressSend.insert(std::make_pair(0x631E81, 0x631E81));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6332A1, 0x6332A1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x633345, 0x633345));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6333B9, 0x6333B9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x633460, 0x633460));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63354B, 0x63354B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x637194, 0x637194));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63B6D7, 0x63B6D7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63B777, 0x63B777));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63B930, 0x63B930));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63D890, 0x63D890));
		Engine->mReturnAdressSend.insert(std::make_pair(0x63F1AC, 0x63F1AC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x642E4E, 0x642E4E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x643A7A, 0x643A7A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x645331, 0x645331));
		Engine->mReturnAdressSend.insert(std::make_pair(0x64EED6, 0x64EED6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x64F41A, 0x64F41A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x64F5AA, 0x64F5AA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6548C2, 0x6548C2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x654952, 0x654952));
		Engine->mReturnAdressSend.insert(std::make_pair(0x655084, 0x655084));
		Engine->mReturnAdressSend.insert(std::make_pair(0x657130, 0x657130));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6689D0, 0x6689D0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x668A44, 0x668A44));
		Engine->mReturnAdressSend.insert(std::make_pair(0x668AEC, 0x668AEC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x668BE0, 0x668BE0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x668FF2, 0x668FF2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x66BAC8, 0x66BAC8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x66BD58, 0x66BD58));
		Engine->mReturnAdressSend.insert(std::make_pair(0x66BDF6, 0x66BDF6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x66BE88, 0x66BE88));
		Engine->mReturnAdressSend.insert(std::make_pair(0x674D10, 0x674D10));
		Engine->mReturnAdressSend.insert(std::make_pair(0x686EC3, 0x686EC3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x689596, 0x689596));
		Engine->mReturnAdressSend.insert(std::make_pair(0x68A33E, 0x68A33E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x68AC5E, 0x68AC5E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x68E54D, 0x68E54D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x68E5E5, 0x68E5E5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x68EBA5, 0x68EBA5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x690AE8, 0x690AE8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6915DC, 0x6915DC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x691726, 0x691726));
		Engine->mReturnAdressSend.insert(std::make_pair(0x691A2B, 0x691A2B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69217E, 0x69217E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6924D4, 0x6924D4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6949DA, 0x6949DA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x694B5E, 0x694B5E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x699D65, 0x699D65));
		Engine->mReturnAdressSend.insert(std::make_pair(0x699E95, 0x699E95));
		Engine->mReturnAdressSend.insert(std::make_pair(0x699FC5, 0x699FC5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69A265, 0x69A265));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69B6D4, 0x69B6D4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69B80F, 0x69B80F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69CDD6, 0x69CDD6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69CE78, 0x69CE78));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69EAE0, 0x69EAE0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x69EC20, 0x69EC20));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6A447D, 0x6A447D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AB0A0, 0x6AB0A0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AB100, 0x6AB100));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AB3E7, 0x6AB3E7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6ABE4E, 0x6ABE4E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6ACB65, 0x6ACB65));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AE0C6, 0x6AE0C6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AE267, 0x6AE267));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AF41A, 0x6AF41A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AF4CC, 0x6AF4CC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AFD44, 0x6AFD44));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AFDCD, 0x6AFDCD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6AFE74, 0x6AFE74));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B0041, 0x6B0041));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B0366, 0x6B0366));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B239A, 0x6B239A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B302B, 0x6B302B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B3190, 0x6B3190));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B3334, 0x6B3334));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B3435, 0x6B3435));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B3545, 0x6B3545));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B39C1, 0x6B39C1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B3B50, 0x6B3B50));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B4906, 0x6B4906));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6B8715, 0x6B8715));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C5B21, 0x6C5B21));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C5B91, 0x6C5B91));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C67B1, 0x6C67B1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C6821, 0x6C6821));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C8731, 0x6C8731));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C87A1, 0x6C87A1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C8CDA, 0x6C8CDA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C8D51, 0x6C8D51));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6C8DF1, 0x6C8DF1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6CD778, 0x6CD778));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6D2764, 0x6D2764));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6D2DC3, 0x6D2DC3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6D36C5, 0x6D36C5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DAE81, 0x6DAE81));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DB326, 0x6DB326));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DB658, 0x6DB658));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DBF9A, 0x6DBF9A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DC31F, 0x6DC31F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD1D0, 0x6DD1D0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD240, 0x6DD240));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD2B0, 0x6DD2B0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD320, 0x6DD320));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD390, 0x6DD390));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD42A, 0x6DD42A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD4CA, 0x6DD4CA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6DD540, 0x6DD540));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E2734, 0x6E2734));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E41DC, 0x6E41DC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E5446, 0x6E5446));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E5593, 0x6E5593));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E5653, 0x6E5653));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E8247, 0x6E8247));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E82B6, 0x6E82B6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6E8326, 0x6E8326));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EBDEC, 0x6EBDEC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EC729, 0x6EC729));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EDD29, 0x6EDD29));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EDD99, 0x6EDD99));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EDE09, 0x6EDE09));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6EDE79, 0x6EDE79));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F055B, 0x6F055B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F195F, 0x6F195F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F1A95, 0x6F1A95));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F1C82, 0x6F1C82));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F318C, 0x6F318C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F331F, 0x6F331F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F3A33, 0x6F3A33));
		Engine->mReturnAdressSend.insert(std::make_pair(0x6F3C97, 0x6F3C97));
		Engine->mReturnAdressSend.insert(std::make_pair(0x707D0C, 0x707D0C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x708EA3, 0x708EA3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x70CA23, 0x70CA23));
		Engine->mReturnAdressSend.insert(std::make_pair(0x70CA93, 0x70CA93));
		Engine->mReturnAdressSend.insert(std::make_pair(0x70EF31, 0x70EF31));
		Engine->mReturnAdressSend.insert(std::make_pair(0x70F13B, 0x70F13B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x728185, 0x728185));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7291A8, 0x7291A8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72A1BF, 0x72A1BF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72A783, 0x72A783));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72CA8E, 0x72CA8E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72CC03, 0x72CC03));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72CCDB, 0x72CCDB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x72CDFE, 0x72CDFE));
		Engine->mReturnAdressSend.insert(std::make_pair(0x737652, 0x737652));
		Engine->mReturnAdressSend.insert(std::make_pair(0x73D65A, 0x73D65A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x73D95F, 0x73D95F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x745F3C, 0x745F3C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x746716, 0x746716));
		Engine->mReturnAdressSend.insert(std::make_pair(0x74B2CB, 0x74B2CB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x74B438, 0x74B438));
		Engine->mReturnAdressSend.insert(std::make_pair(0x74E38A, 0x74E38A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x74F2BF, 0x74F2BF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x758801, 0x758801));
		Engine->mReturnAdressSend.insert(std::make_pair(0x759B03, 0x759B03));
		Engine->mReturnAdressSend.insert(std::make_pair(0x759C41, 0x759C41));
		Engine->mReturnAdressSend.insert(std::make_pair(0x75F105, 0x75F105));
		Engine->mReturnAdressSend.insert(std::make_pair(0x75FF29, 0x75FF29));
		Engine->mReturnAdressSend.insert(std::make_pair(0x75FF90, 0x75FF90));
		Engine->mReturnAdressSend.insert(std::make_pair(0x760343, 0x760343));
		Engine->mReturnAdressSend.insert(std::make_pair(0x763F86, 0x763F86));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76406B, 0x76406B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76A127, 0x76A127));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76C6F9, 0x76C6F9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76C769, 0x76C769));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76C872, 0x76C872));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76E367, 0x76E367));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76E40A, 0x76E40A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x76E4AD, 0x76E4AD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7767F0, 0x7767F0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x778543, 0x778543));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7789DA, 0x7789DA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x778AD0, 0x778AD0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x77D411, 0x77D411));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7820E9, 0x7820E9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7853D0, 0x7853D0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x785C70, 0x785C70));
		Engine->mReturnAdressSend.insert(std::make_pair(0x78876D, 0x78876D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7889EA, 0x7889EA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x788C24, 0x788C24));
		Engine->mReturnAdressSend.insert(std::make_pair(0x788CD1, 0x788CD1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x78D5F6, 0x78D5F6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x78F654, 0x78F654));
		Engine->mReturnAdressSend.insert(std::make_pair(0x790703, 0x790703));
		Engine->mReturnAdressSend.insert(std::make_pair(0x790947, 0x790947));
		Engine->mReturnAdressSend.insert(std::make_pair(0x790F2B, 0x790F2B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x79264F, 0x79264F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7929CF, 0x7929CF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7A2675, 0x7A2675));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7A291E, 0x7A291E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7A2A69, 0x7A2A69));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7A6FC7, 0x7A6FC7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7A8B9B, 0x7A8B9B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7BF6D8, 0x7BF6D8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7C036C, 0x7C036C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7C03BF, 0x7C03BF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7C1702, 0x7C1702));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7C1A33, 0x7C1A33));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7C542C, 0x7C542C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CA5C2, 0x7CA5C2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CA726, 0x7CA726));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CAB4F, 0x7CAB4F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CABA2, 0x7CABA2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CAC7F, 0x7CAC7F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7CACD2, 0x7CACD2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D38B4, 0x7D38B4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D57F5, 0x7D57F5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D5FA4, 0x7D5FA4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D650D, 0x7D650D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D659D, 0x7D659D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D8CCC, 0x7D8CCC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D981C, 0x7D981C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D98A9, 0x7D98A9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7D991C, 0x7D991C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7E96B3, 0x7E96B3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7E9803, 0x7E9803));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7ED6B3, 0x7ED6B3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7ED793, 0x7ED793));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7EF3EF, 0x7EF3EF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7F262F, 0x7F262F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7F77E1, 0x7F77E1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x7F9457, 0x7F9457));
		Engine->mReturnAdressSend.insert(std::make_pair(0x82BDE4, 0x82BDE4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8316EA, 0x8316EA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x833334, 0x833334));
		Engine->mReturnAdressSend.insert(std::make_pair(0x833501, 0x833501));
		Engine->mReturnAdressSend.insert(std::make_pair(0x833BF0, 0x833BF0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x833E99, 0x833E99));
		Engine->mReturnAdressSend.insert(std::make_pair(0x859BC9, 0x859BC9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x85B80D, 0x85B80D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x864F66, 0x864F66));
		Engine->mReturnAdressSend.insert(std::make_pair(0x87BC30, 0x87BC30));
		Engine->mReturnAdressSend.insert(std::make_pair(0x87BCB9, 0x87BCB9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x87F5C7, 0x87F5C7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x880FC8, 0x880FC8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x883476, 0x883476));
		Engine->mReturnAdressSend.insert(std::make_pair(0x88362F, 0x88362F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x884900, 0x884900));
		Engine->mReturnAdressSend.insert(std::make_pair(0x889055, 0x889055));
		Engine->mReturnAdressSend.insert(std::make_pair(0x88CCDB, 0x88CCDB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x88CD42, 0x88CD42));
		Engine->mReturnAdressSend.insert(std::make_pair(0x88CE7B, 0x88CE7B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x88FFE7, 0x88FFE7));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8900F3, 0x8900F3));
		Engine->mReturnAdressSend.insert(std::make_pair(0x891775, 0x891775));
		Engine->mReturnAdressSend.insert(std::make_pair(0x895D97, 0x895D97));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8A8814, 0x8A8814));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8AC563, 0x8AC563));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8ADD78, 0x8ADD78));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8AE58B, 0x8AE58B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8B7091, 0x8B7091));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BAAEA, 0x8BAAEA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BAB6A, 0x8BAB6A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BC71A, 0x8BC71A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BC79A, 0x8BC79A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BE68A, 0x8BE68A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8BE6F0, 0x8BE6F0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8C1D2C, 0x8C1D2C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8C2EEC, 0x8C2EEC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8C3551, 0x8C3551));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8C8DE5, 0x8C8DE5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8CA8C5, 0x8CA8C5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8CA95C, 0x8CA95C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8CA9FF, 0x8CA9FF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8CB6DD, 0x8CB6DD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D0FAB, 0x8D0FAB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D12DF, 0x8D12DF));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D1CC1, 0x8D1CC1));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D7C4C, 0x8D7C4C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D7CC9, 0x8D7CC9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D7D88, 0x8D7D88));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D81D8, 0x8D81D8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8D8336, 0x8D8336));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E2480, 0x8E2480));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E5DE9, 0x8E5DE9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E5E66, 0x8E5E66));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E5F0E, 0x8E5F0E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E6906, 0x8E6906));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E6A36, 0x8E6A36));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8E93CD, 0x8E93CD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8EEBE0, 0x8EEBE0));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8EEC52, 0x8EEC52));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8EECC2, 0x8EECC2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8EED32, 0x8EED32));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8F109C, 0x8F109C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8F9991, 0x8F9991));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8F9A71, 0x8F9A71));
		Engine->mReturnAdressSend.insert(std::make_pair(0x8FDEF4, 0x8FDEF4));
		Engine->mReturnAdressSend.insert(std::make_pair(0x901F5C, 0x901F5C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x902850, 0x902850));
		Engine->mReturnAdressSend.insert(std::make_pair(0x90830A, 0x90830A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9084E8, 0x9084E8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x91044D, 0x91044D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x910779, 0x910779));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9107FC, 0x9107FC));
		Engine->mReturnAdressSend.insert(std::make_pair(0x911D4F, 0x911D4F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9123BA, 0x9123BA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9124EE, 0x9124EE));
		Engine->mReturnAdressSend.insert(std::make_pair(0x912781, 0x912781));
		Engine->mReturnAdressSend.insert(std::make_pair(0x912B0A, 0x912B0A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x912E4C, 0x912E4C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x917B55, 0x917B55));
		Engine->mReturnAdressSend.insert(std::make_pair(0x91AE77, 0x91AE77));
		Engine->mReturnAdressSend.insert(std::make_pair(0x91AF7E, 0x91AF7E));
		Engine->mReturnAdressSend.insert(std::make_pair(0x91AFF6, 0x91AFF6));
		Engine->mReturnAdressSend.insert(std::make_pair(0x92664B, 0x92664B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x94D7F5, 0x94D7F5));
		Engine->mReturnAdressSend.insert(std::make_pair(0x95D35A, 0x95D35A));
		Engine->mReturnAdressSend.insert(std::make_pair(0x95DADA, 0x95DADA));
		Engine->mReturnAdressSend.insert(std::make_pair(0x95E227, 0x95E227));
		Engine->mReturnAdressSend.insert(std::make_pair(0x95E520, 0x95E520));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99C3A9, 0x99C3A9));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99E8D2, 0x99E8D2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99E902, 0x99E902));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99E936, 0x99E936));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99E966, 0x99E966));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99E996, 0x99E996));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99EA58, 0x99EA58));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99EA88, 0x99EA88));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99EAE2, 0x99EAE2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99ED06, 0x99ED06));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99F148, 0x99F148));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99F1B8, 0x99F1B8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x99F258, 0x99F258));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9A0102, 0x9A0102));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9A2537, 0x9A2537));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9A8CFB, 0x9A8CFB));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9A9A2B, 0x9A9A2B));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9B449F, 0x9B449F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9B6A5C, 0x9B6A5C));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9B6B4F, 0x9B6B4F));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9BD7FD, 0x9BD7FD));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9CC5B2, 0x9CC5B2));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9CC672, 0x9CC672));
		Engine->mReturnAdressSend.insert(std::make_pair(0x9CE4A8, 0x9CE4A8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4C3180, 0x4C3180));
		Engine->mReturnAdressSend.insert(std::make_pair(0x4C331D, 0x4C331D));
		Engine->mReturnAdressSend.insert(std::make_pair(0x93AFE8, 0x93AFE8));
		Engine->mReturnAdressSend.insert(std::make_pair(0x93B0F7, 0x93B0F7));
	}
}
// pm hook
typedef void(WINAPI* tGetChild)(const std::string& szString, DWORD nUnkown);
tGetChild oGetChild;
typedef void(WINAPI* tSetUIPos)(int x, int y);
tSetUIPos oSetUIPos;
typedef void(WINAPI* htSetVisible)(bool isVisible);
htSetVisible oSetVisible;
string tmp_gc_string = "";
//void __stdcall SetVisible_Hook(bool isVisible)
//{
//	DWORD thisPtr;
//	__asm
//	{
//		MOV thisPtr, ECX
//	}
//
//	if (Engine->varius
//		&& thisPtr == Engine->varius
//		&& Engine->uiState && isVisible)
//		Engine->uiState->resetPerks();
//
//	/*if (Engine->uiTradeInventory != NULL && isVisible && Engine->uiTradeInventory->m_dVTableAddr == thisPtr)
//	{
//		Engine->SetString(Engine->uiTradeInventory->text_sell_KnightCash, "0");
//		Engine->SetString(Engine->uiTradeInventory->text_sell_money, "0");
//	}*/
//	if (Engine->uiSeedHelperPlug != NULL && thisPtr == Engine->uiSeedHelperPlug->group_option_grapic2)
//	{
//		Engine->SetState(Engine->uiSeedHelperPlug->btn_render_objects, isRenderObject ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
//		Engine->SetState(Engine->uiSeedHelperPlug->btn_hide_player, isHideUser ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
//	}
//	if (Engine->uiGenieMain != NULL && Engine->uiGenieMain->etc == thisPtr && isVisible)
//	{
//		Engine->SetState(Engine->uiGenieMain->btn_party_leader_on, isLeaderAttack ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
//		Engine->SetState(Engine->uiGenieMain->btn_party_leader_off, isLeaderAttack ? UI_STATE_BUTTON_NORMAL : UI_STATE_BUTTON_DOWN);
//	}
//	//Genie YNG
//#if 0
//	if (Engine->GenieStartControl)
//	{
//		if (Engine->uiGenieSubPlug != NULL)
//		{
//			if (thisPtr == Engine->uiGenieSubPlug->TargetSam || thisPtr == Engine->uiGenieSubPlug->TargetTwo)
//			{
//
//#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
//				POINT pt;
//				Engine->GetUiPos(Engine->hkServerNotice, pt);
//				LONG isPost = 63;
//
//
//				if (thisPtr == Engine->uiGenieSubPlug->TargetSam && isVisible)
//					isPost = 115;
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetSam && !isVisible)
//				{
//					if (Engine->IsVisible(thisPtr))
//						isPost = 89;
//				}
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && !isVisible)
//					isPost = 47;
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && isVisible)
//					isPost = 93;	//1098 genieye göre target two ayarlandi. v2 de kontrol edilecek.
//#else
//				POINT pt;
//				Engine->GetUiPos(Engine->hkServerNotice, pt);
//				LONG isPost = 69;
//
//
//				if (thisPtr == Engine->uiGenieSubPlug->TargetSam && isVisible)
//					isPost = 117;
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetSam && !isVisible)
//				{
//					if (Engine->IsVisible(thisPtr))
//						isPost = 93;
//				}
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && !isVisible)
//					isPost = 47;
//				else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && isVisible)
//					isPost = 93;	//2369 genieye göre target two ayarlandi. v2 de kontrol edilecek.
//#endif
//
//				RECT ASD = Engine->GetUiRegion(Engine->uiGenieSubPlug->m_dVTableAddr);
//
//				ASD.bottom = isPost;
//
//				Engine->SetUiRegion(Engine->uiGenieSubPlug->m_dVTableAddr, ASD);
//				if (Engine->IsVisible(Engine->hkCampAdress))
//					(LONG)isPost += 18;
//				POINT zs;
//				zs.x = pt.x;
//				zs.y = isPost;
//				Engine->SetUIPos(Engine->hkServerNotice, zs);
//				if (Engine->IsVisible(Engine->hkCampAdress))
//				{
//
//					Engine->GetUiPos(Engine->hkCampAdress, pt);
//
//					zs.y = LONG(isPost - 22);
//					Engine->SetUIPos(Engine->hkCampAdress, zs);
//				}
//
//				POINT z2;
//
//#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
//				z2.x = LONG(koScreen.x - 169);
//				z2.y = 0;
//#else
//				z2.x = LONG(koScreen.x - 187);
//				z2.y = 0;
//#endif
//				Engine->SetUIPos(Engine->uiGenieSubPlug->m_dVTableAddr, z2);
//			}
//		}
//	}
//#endif
//	_asm
//	{
//		MOV ECX, thisPtr
//		PUSH isVisible
//		CALL oSetVisible
//	}
//}
void __stdcall SetVisible_Hook(bool isVisible)
{
	DWORD thisPtr;
	__asm
	{
		MOV thisPtr, ECX
	}

	if (Engine->varius
		&& thisPtr == Engine->varius
		&& Engine->uiState && isVisible)
		Engine->uiState->resetPerks();

	if (Engine->uiSeedHelperPlug != NULL && thisPtr == Engine->uiSeedHelperPlug->group_option_grapic2)
	{
		Engine->SetState(Engine->uiSeedHelperPlug->btn_render_objects, isRenderObject ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
		Engine->SetState(Engine->uiSeedHelperPlug->btn_hide_player, isHideUser ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
	}
	if (Engine->uiGenieMain != NULL && Engine->uiGenieMain->etc == thisPtr && isVisible)
	{
		Engine->SetState(Engine->uiGenieMain->btn_party_leader_on, isLeaderAttack ? UI_STATE_BUTTON_DOWN : UI_STATE_BUTTON_NORMAL);
		Engine->SetState(Engine->uiGenieMain->btn_party_leader_off, isLeaderAttack ? UI_STATE_BUTTON_NORMAL : UI_STATE_BUTTON_DOWN);
	}
#if 0
	if (Engine->uiGenieSubPlug != NULL)
	{
		if (thisPtr == Engine->uiGenieSubPlug->TargetSam || thisPtr == Engine->uiGenieSubPlug->TargetTwo)
		{
#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
			POINT pt;
			Engine->GetUiPos(Engine->hkServerNotice, pt);
			LONG isPost = 63;
			if (thisPtr == Engine->uiGenieSubPlug->TargetSam && isVisible)
				isPost = 115;
			else if (thisPtr == Engine->uiGenieSubPlug->TargetSam && !isVisible)
			{
				if (Engine->IsVisible(thisPtr))
					isPost = 89;
			}
			else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && !isVisible)
				isPost = 47;
			else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && isVisible)
				isPost = 93;	//1098 genieye göre target two ayarlandı. v2 de kontrol edilecek.
#else
			POINT pt;
			Engine->GetUiPos(Engine->hkServerNotice, pt);
			LONG isPost = 69;

			if (thisPtr == Engine->uiGenieSubPlug->TargetSam && isVisible)
				isPost = 117;
			else if (thisPtr == Engine->uiGenieSubPlug->TargetSam && !isVisible)
			{
				if (Engine->IsVisible(thisPtr))
					isPost = 93;
			}
			else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && !isVisible)
				isPost = 47;
			else if (thisPtr == Engine->uiGenieSubPlug->TargetTwo && isVisible)
				isPost = 93;	//2369 genieye göre target two ayarlandı. v2 de kontrol edilecek.
#endif
			RECT ASD = Engine->GetUiRegion(Engine->uiGenieSubPlug->m_dVTableAddr);
			ASD.bottom = isPost;
			Engine->SetUiRegion(Engine->uiGenieSubPlug->m_dVTableAddr, ASD);

			if (Engine->IsVisible(Engine->hkCampAdress))
				isPost += 18;

			POINT zs;
			zs.x = pt.x;
			zs.y = isPost;
			Engine->SetUIPos(Engine->hkServerNotice, zs);
			if (Engine->IsVisible(Engine->hkCampAdress))
			{
				Engine->GetUiPos(Engine->hkCampAdress, pt);
				zs.y = LONG(isPost - 22);
				Engine->SetUIPos(Engine->hkCampAdress, zs);
			}
			POINT z2;
#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
			z2.x = LONG(koScreen.x - 169);
			z2.y = 0;
#else
			z2.x = LONG(koScreen.x - 187);
			z2.y = 0;
#endif
			Engine->SetUIPos(Engine->uiGenieSubPlug->m_dVTableAddr, z2);
		}
	}
#endif

	// UYARI GİDERİLDİ: 'bool' (1 byte) yerine 'DWORD' (4 byte) stack'e pushlanarak geçersiz yönerge uyarısı çözüldü.
	DWORD dwVisible = isVisible;
	_asm
	{
		MOV ECX, thisPtr
		PUSH dwVisible
		CALL oSetVisible
	}
}
void __stdcall SetUI_Hook(int x, int y)
{
	DWORD thisPtr;

	__asm
	{
		MOV thisPtr, ECX
	}

#if 0
	if (g_pMain->uiGenieSubPlug && g_pMain->uiGenieSubPlug->m_dVTableAddr == thisPtr)
	{
		koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
		POINT pt;
		g_pMain->GetUiPos(thisPtr, pt);


#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
		x = LONG(koScreen.x - 169);
		y = 0;
#else
		x = LONG(koScreen.x - 187);
		y = 0;
#endif
	}
	else
	{

		if (g_pMain->uiGenieSubPlug
			&& g_pMain->m_bGameStart
			&& g_pMain->uiGenieSubPlug->m_dVTableAddr != NULL)
		{

			POINT zs;
#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
			zs.x = LONG(koScreen.x - 169);
			zs.y = 0;
#else
			zs.x = LONG(koScreen.x - 187);
			zs.y = 0;
#endif
			g_pMain->SetUIPos(g_pMain->uiGenieSubPlug->m_dVTableAddr, zs);
		}
	}
#endif
	_asm
	{
		MOV ECX, thisPtr
		PUSH y
		push x
		CALL oSetUIPos
	}
}
void __stdcall GetChildByID_Hook(const std::string& szString, DWORD nUnkown)
{

	DWORD thisPtr;
	__asm
	{
		MOV thisPtr, ECX
		pushad
		pushfd
	}

	tmp_gc_string = szString;
	if (tmp_gc_string == "btn_ch0")
		Engine->hkCampAdress = thisPtr;

	if (tmp_gc_string == "Group_SelectWindow" && Engine->Adress == 0)
	{
		Engine->Adress = thisPtr;

	}


	if (tmp_gc_string == "exit_id")
	{
		DWORD tmp = 0;
		Engine->GetChildByID(thisPtr, "btn_open", tmp);

		if (tmp) // whisper_close
		{
			Engine->privatemessages.push_back(new HookPM(thisPtr, false));
		}
		else { // whisper open
			Engine->privatemessages.push_back(new HookPM(thisPtr, true));
		}
	}

	_asm
	{
		popfd
		popad
		MOV ECX, thisPtr
		MOV EAX, szString
		push nUnkown
		PUSH EAX
		CALL oGetChild

	}
}


typedef HINSTANCE(WINAPI* tShellExecuteA)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd);
tShellExecuteA oShellExecuteA;

HINSTANCE WINAPI hkShellExecuteA(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd)
{
	string tmp = lpFile;
	if (Engine->StringHelper->IsContains(tmp, "explore")) {
		exit(0);
		return (HINSTANCE)0x90;
	}
	else
		return oShellExecuteA(hwnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd);
}

//Skill Range Start
const DWORD Func_AreaMove = 0x5B18B9; //2369

int tmpRange = 0;
float rangeLimit = 999.0f;
bool outofRange = false;
float charX = 0, charY = 0, charZ = 0;
float X = 0, Y = 0, Z = 0;
float nearstX = 0, nearstZ = 0;

bool isInRectangle(float centerX, float centerY, float radius, float x, float y)
{
	return x >= centerX - radius && x <= centerX + radius && y >= centerY - radius && y <= centerY + radius;
}

bool isPointInCircle(float centerX, float centerY, float radius, float x, float y)
{
	if (isInRectangle(centerX, centerY, radius, x, y))
	{
		float dx = centerX - x;
		float dy = centerY - y;
		dx *= dx;
		dy *= dy;
		float distanceSquared = dx + dy;
		float radiusSquared = radius * radius;
		return distanceSquared <= radiusSquared;
	}
	return false;
}

void __fastcall CalculateNearestPoint()
{
	float vX = X - charX;
	float vY = Z - charZ;
	float magV = sqrt(vX * vX + vY * vY);
	float aX = charX + vX / magV * rangeLimit;
	float aY = charZ + vY / magV * rangeLimit;

	nearstX = aX;
	nearstZ = aY;
}

bool skillRange = true;  // Alan Skili Açma ve kapama -True - False 
DWORD nEAX = 0;

DWORD __declspec(naked) hkAreaMove()
{

	__asm {
		cmp byte ptr skillRange, 0
		jz gec
		cmp ebx, 0x00002734 // y??e mi alan skill mi
		je limitle
		cmp ebx, 0x00002737 // y??e mi alan skill mi
		je limitle
		gec :
		mov ecx, [ebp + 0x10]
			fld dword ptr[ecx]
			fstp dword ptr[eax + 0x12C]
			fld dword ptr[ecx + 4]
			fstp dword ptr[eax + 0x130]
			fld dword ptr[ecx + 8]
			fstp dword ptr[eax + 0x134]
			push 0x005B18D6
			ret
			limitle :
		mov edx, [KO_PTR_CHR]
			mov edx, [edx]
			fld dword ptr[edx + 0xEC]
			fstp dword ptr charX
			fld dword ptr[edx + 0xF0]
			fstp dword ptr charY
			fld dword ptr[edx + 0xF4]
			fstp dword ptr charZ
			mov ecx, [ebp + 0x10]
			fld dword ptr[ecx]
			fstp dword ptr X
			fld dword ptr[ecx + 4]
			fstp dword ptr Y
			fld dword ptr[ecx + 8]
			fstp dword ptr Z
			fld dword ptr[ecx + 4]
			fstp dword ptr[eax + 0x130]
			pushad
	}
	outofRange = !isPointInCircle(charX, charZ, rangeLimit, X, Z);
	__asm {
		call CalculateNearestPoint
		popad
		cmp byte ptr outofRange, 0
		je gec
		fld dword ptr nearstX
		fstp dword ptr[eax + 0x12C]
		fld dword ptr[eax + 0x12C]
		fstp dword ptr[ecx]
		fld dword ptr charY
		fstp dword ptr[eax + 0x130]
		fld dword ptr[eax + 0x130]
		fstp dword ptr[ecx + 4]
		fld dword ptr nearstZ
		fstp dword ptr[eax + 0x134]
		fld dword ptr[eax + 0x134]
		fstp dword ptr[ecx + 8]
		push 0x005B18D6
		ret
	}
}

const DWORD Func_RangeInstance = 0x94D057; //2369

DWORD __declspec(naked) hkRangeInstance()
{
	__asm {
		pushad
		mov eax, [edi + 0xC0]
		mov tmpRange, eax
		dec tmpRange
		movd xmm0, tmpRange
		cvtdq2ps xmm0, xmm0
		movss rangeLimit, xmm0
		popad
		mov eax, 0x4037D0
		call eax
		mov edx, [Func_RangeInstance]
		mov ebx, 5
		add edx, ebx
		push edx
		ret
	}
}
//Skill Range End
bool PearlEngine::TitleWindow(int /*id*/, LPCSTR WindowTitle)
{
	//	if (FindWindowA(NULL, WindowTitle) > 0) {
	//		//return false;
	//#if ANTICHEAT_MODE == 1
	//		Shutdown(string_format(xorstr("Cheat Detected %d", id)));
	//#endif
	//	}
	//	return true;

	HWND hWnds = FindWindowA(NULL, (LPCTSTR)WindowTitle);
	if (hWnds != NULL)
	{
#if ANTICHEAT_MODE == 0
		// UYARI GİDERİLDİ (C4100): id kullanılmadığı için string formatından çıkarıldı.
		Shutdown(string_format(xorstr("Cheat Detected 0x00FF1")));
#endif
	}
	return true;
}

#include <string>
#include <chrono>

// UYARI GİDERİLDİ (C4100): 'e' parametresi kullanılmadığı için yoruma alındı.
DWORD WINAPI PearlEngine::TitleCheck(PearlEngine* /*e*/)
{
	Sleep(30000);
	VIRTUALIZER_START
		while (true)
		{
			Sleep(5000);
			HWND hWnd = GetForegroundWindow();
			int dwExStyle = (DWORD)GetWindowLong(hWnd, GWL_EXSTYLE);
			if (dwExStyle == (int)65808)
				Engine->Shutdown(xorstr("Cheat edited Detected 0x1"));

			int id = 1;

			// OPTİMİZASYON: 1000 kere dönen ve sistemi donduran iç içe 3'lü for döngüsü silindi.
			// Bunun yerine doğrudan API'ye statik stringler gönderiliyor. Bu sayede anlık takılmalar (stutter) çözüldü.

			Engine->TitleWindow(id++, "Cheat Engine"); // Sürüm yazmasa bile ana başlık çoğunu yakalar
			Engine->TitleWindow(id++, "Cheat Engine 7.4");
			Engine->TitleWindow(id++, "Cheat Engine 7.5");

			Engine->TitleWindow(id++, "Add address");
			Engine->TitleWindow(id++, "ArtMoney PRO v7.27");
			Engine->TitleWindow(id++, "ArtMoney SE v7.31");
			Engine->TitleWindow(id++, "ArtMoney SE v7.32");
			Engine->TitleWindow(id++, "Cheat Engine 5.0");
			Engine->TitleWindow(id++, "Cheat Engine 5.1");
			Engine->TitleWindow(id++, "Cheat Engine 5.1.1");
			Engine->TitleWindow(id++, "Cheat Engine 5.2");
			Engine->TitleWindow(id++, "Cheat Engine 5.3");
			Engine->TitleWindow(id++, "Cheat Engine 5.4");
			Engine->TitleWindow(id++, "Cheat Engine 5.5");
			Engine->TitleWindow(id++, "Cheat Engine 5.6");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.1");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.2");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.3");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.4");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.5");
			Engine->TitleWindow(id++, "Cheat Engine 5.6.6");
			Engine->TitleWindow(id++, "Cheat Engine 6.0");
			Engine->TitleWindow(id++, "Cheat Engine 6.1");
			Engine->TitleWindow(id++, "Cheat Engine 6.2");
			Engine->TitleWindow(id++, "Cheat Engine 6.3");
			Engine->TitleWindow(id++, "Cheat Engine 6.4");
			Engine->TitleWindow(id++, "Cheat Engine 6.5");
			Engine->TitleWindow(id++, "Cheat Engine 6.6");
			Engine->TitleWindow(id++, "Cheat Engine 6.7");
			Engine->TitleWindow(id++, "Cheat Engine 7.0");
			Engine->TitleWindow(id++, "Cheat Engine 7.1");
			Engine->TitleWindow(id++, "Cheat Engine 7.2");
			Engine->TitleWindow(id++, "Cheat Engine 7.3");
			Engine->TitleWindow(id++, "Created processes");
			Engine->TitleWindow(id++, "D-C Bypass");
			Engine->TitleWindow(id++, "DC-BYPASS By DjCheats  Public Vercion");
			Engine->TitleWindow(id++, "HiDeToolz");
			Engine->TitleWindow(id++, "HideToolz");
			Engine->TitleWindow(id++, "Injector");
			Engine->TitleWindow(id++, "Olly Debugger");
			Engine->TitleWindow(id++, "Process Explorer 11.33");
			Engine->TitleWindow(id++, "Process Explorer");
			Engine->TitleWindow(id++, "T Search");
			Engine->TitleWindow(id++, "WPE PRO");
			Engine->TitleWindow(id++, "WPePro 0.9a");
			Engine->TitleWindow(id++, "WPePro 1.3");
			Engine->TitleWindow(id++, "hacker");
			Engine->TitleWindow(id++, "rPE - rEdoX Packet Editor");
			Engine->TitleWindow(id++, "OllyDbg");
			Engine->TitleWindow(id++, "HxD");
			Engine->TitleWindow(id++, "Process Hacker 2");
			Engine->TitleWindow(id++, "Process Hacker");
			Engine->TitleWindow(id++, "Ultimate Cheat");
			Engine->TitleWindow(id++, "The following opcodes accessed the selected address");
			Engine->TitleWindow(id++, "lalaker1");
			Engine->TitleWindow(id++, "IDA!");
			Engine->TitleWindow(id++, "The interactive disassembler");
			Engine->TitleWindow(id++, "1nj3ct0r");
			Engine->TitleWindow(id++, "injector");
			Engine->TitleWindow(id++, "dreamfancy");
			Engine->TitleWindow(id++, "pvp hile indir");
			Engine->TitleWindow(id++, "Knight Online tr hile indir");
			Engine->TitleWindow(id++, "Knight Online oyun hileleri sitesi 2015");
			Engine->TitleWindow(id++, "Knight Online Hilecim");
			Engine->TitleWindow(id++, "Knight Online Hileleri");
			Engine->TitleWindow(id++, "Knight Online Hile indir");
			Engine->TitleWindow(id++, "Online Oyun Hileleri");
			Engine->TitleWindow(id++, "N-Jector by NOOB");
			Engine->TitleWindow(id++, "[BETA] Hack Loader v1.0.2");
			Engine->TitleWindow(id++, "[BETA] Hack Loader v1.0.3");
			Engine->TitleWindow(id++, "Wallhack");
			Engine->TitleWindow(id++, "Pro Damage");
			Engine->TitleWindow(id++, "Wait Damage (7x)");
			Engine->TitleWindow(id++, "Okçu hilesi");
			Engine->TitleWindow(id++, "Daily Stage 2 (Günlük Asama 2 )");
			Engine->TitleWindow(id++, "Injector [FaithDEV]");
			Engine->TitleWindow(id++, "Injector Gadget");
			Engine->TitleWindow(id++, "Themida");
			Engine->TitleWindow(id++, "HiDeToolz");
			Engine->TitleWindow(id++, "HideToolz");
			Engine->TitleWindow(id++, "dreamfancy");
			Engine->TitleWindow(id++, "Injector");
			Engine->TitleWindow(id++, "OldSchoolInject");
			Engine->TitleWindow(id++, "Extreme Injector");
			Engine->TitleWindow(id++, "| Fortis Fortuna Adiuvat |");
			Engine->TitleWindow(id++, "PHTrenbot");
			Engine->TitleWindow(id++, "Process Lasso");
			Engine->TitleWindow(id++, "System Explorer 7.0.0.5356");
			Engine->TitleWindow(id++, "Exe String Editore");
			Engine->TitleWindow(id++, "DaveLombardo");
			Engine->TitleWindow(id++, "ShowString");
			Engine->TitleWindow(id++, "TAMORY");
			Engine->TitleWindow(id++, "snoxd");
			Engine->TitleWindow(id++, "SQL Scripts");
			Engine->TitleWindow(id++, "odbg201");
			Engine->TitleWindow(id++, "odbg202");
			Engine->TitleWindow(id++, "OLLYDBG");
			Engine->TitleWindow(id++, "ollydbG");
			Engine->TitleWindow(id++, "PhantOm");
			Engine->TitleWindow(id++, "Themida");
			Engine->TitleWindow(id++, "Pointer Bulucu");
			Engine->TitleWindow(id++, "OTO POINTER");
			Engine->TitleWindow(id++, "Oto Pointer");
			Engine->TitleWindow(id++, "HDRExporter");
			Engine->TitleWindow(id++, "MoleBox Pro 2.6.4.2534");
			Engine->TitleWindow(id++, "MoleBox Pro 2.6.4");
			Engine->TitleWindow(id++, "otoPointer");
			Engine->TitleWindow(id++, "Tbl Editör");
			Engine->TitleWindow(id++, "Themida v1");
			Engine->TitleWindow(id++, "Hooking");
			Engine->TitleWindow(id++, "SOACS_Yourko_2017");
			Engine->TitleWindow(id++, "Dll-Injectorv2 by Padmak");
			Engine->TitleWindow(id++, "ThunderRT6FormDC");
			Engine->TitleWindow(id++, "KoPluginGlobal_v7.0.8");
			Engine->TitleWindow(id++, "PaidBot");
			Engine->TitleWindow(id++, "Extreme Injector v3.5 by master131");
			Engine->TitleWindow(id++, "Multi Macro Bot 1.0");
			Engine->TitleWindow(id++, "VMware vSphere Client");
			Engine->TitleWindow(id++, "Okcu Hilesi");
			Engine->TitleWindow(id++, "MyPacketTool");

			Sleep(30000);
		}
	VIRTUALIZER_END
}

extern HANDLE myMutex;
DWORD KO_FNC_OBJECT_PLAYER_LOOP_ORG;
extern NOTIFYICONDATA nid;

void __declspec(naked) hkEndGame()
{
	__asm {
		pushad
		pushfd
	}
	Shell_NotifyIcon(NIM_DELETE, &nid);
	Engine->render = false;
	if (myMutex)
	{
		ReleaseMutex(myMutex);
	}


	if (!Engine->m_bGameStart)
		TerminateProcess(GetCurrentProcess(), 1);
	__asm {
		popfd
		popad
		call KO_CALL_END_GAME
		mov edx, KO_FNC_END_GAME
		add edx, 5
		jmp edx
	}
}

DWORD zoneID = 0;
DWORD kontrolAdresi = 0x55EA7E;  // 2369
DWORD rankiAc = 0x55EA93;  // 2369

void __declspec(naked) hkRank()
{
	__asm
	{
		mov eax, [ECX + 0xCF0] // 2369
		mov zoneID, eax
		pushad
		pushfd
	}

	if (isInSpecialEventZone(zoneID) || zoneID == BIFROST || isInWarZone(zoneID))
		__asm jmp rankiActir;

	__asm {
		popfd
		popad
		mov edx, kontrolAdresi
		add edx, 6
		jmp edx
		rankiActir :
		popfd
			popad
			jmp rankiAc
	}
}

// Anti afk ve kafaya yazi
DWORD fncScanZ = 0x58C7B8,/* 0x00563B8E,*/ keepZ = fncScanZ + 5, retNopZ = fncScanZ + 0x3F; //2369
DWORD fncScanB = 0x58BEED,/* 0x00563489,*/ keepB = fncScanB + 5, retNopB = fncScanB + 0x36; //2369
std::string objTMPString = "";
void SetInfoString(DWORD obj, std::string text, DWORD color, DWORD fontStyle)
{
	(void)fontStyle; // UYARI GİDERİLDİ (C4100)
	objTMPString = text + " ";
	DWORD loc_b = obj; // UYARI GİDERİLDİ: 'b' RGB globaliyle çakışıyordu (C4459)
	__asm {
		push color
		push offset objTMPString
		mov ecx, loc_b
		call KO_FNC_SET_INFO_STRING
	}
}

bool __fastcall IsAntiAFK(DWORD mobBase)
{
	if (!mobBase) return false;

	uint16 protoID = *(uint16*)(mobBase + KO_SSID);
	if (std::find(antiAFKProto.begin(), antiAFKProto.end(), protoID) != antiAFKProto.end())
		return true;

	uint16 protoID2 = *(uint16*)(mobBase + KO_OFF_ID);
	if (Engine->m_isGenieStatus && isLeaderAttack && Engine->isInParty())
	{
		if (Engine->GetPartyLeaderTarget() == protoID2)
			return false;

		return true;
	}
	//if (protoID < NPC_BAND) // oyuncuysa  seçme
	//	return true; 

	return std::find(antiAFKProto.begin(), antiAFKProto.end(), protoID) != antiAFKProto.end();
}
bool __fastcall IsAntiAFK2(DWORD mobBase)
{
	if (!mobBase) return false;

	uint16 protoID = *(uint16*)(mobBase + KO_SSID);

	return std::find(antiAFKProto.begin(), antiAFKProto.end(), protoID) != antiAFKProto.end();
}

DWORD tBase = 0;
void __declspec(naked) hkZ()
{
	__asm {
		call orgCall

		pushad
		pushfd
		mov ecx, esi
		call IsAntiAFK
		movzx eax, al
		test eax, eax
		jne antiafkZ
		popfd
		popad
		mov byte ptr ds : [0x58C7D0] , 0x75
		jmp keepZ
		antiafkZ :

		popfd
			popad
			/*fstp dword ptr[esp + 0x14]
			fld dword ptr[esp + 0x14]
			fld dword ptr[esp + 0x10]

			fnstsw ax
			test ah,41
			fstp st(0)*/
			//jmp retNopZ
			mov byte ptr ds : [0x58C7D0] , 0xEB
			jmp keepZ
	}
}

void __declspec(naked) hkB()
{
	__asm {
		call orgCall
		pushad
		pushfd
		mov ecx, esi
		call IsAntiAFK
		movzx eax, al
		test eax, eax
		jne antiafkB
		popfd
		popad
		mov byte ptr ds : [0x58BF05] , 0x75
		jmp keepB
		antiafkB :
		popfd
			popad
			//jmp retNopB
			mov byte ptr ds : [0x58BF05] , 0xEB
			jmp keepB
	}
}

void __declspec(naked) hkGenieSelect()
{
	__asm {
		call KO_FNC_GENIE_SELECT_ORG_CALL
		pushad
		pushfd
		mov ecx, eax
		call IsAntiAFK
		movzx eax, al
		test eax, eax
		jne antiafkB
		popfd
		popad
		jmp KO_FNC_GENIE_SELECT_RET
		antiafkB :
		popfd
			popad
			xor eax, eax
			jmp KO_FNC_GENIE_SELECT_RET
	}
}
DWORD GetLevelColor(int diff)
{
	if (diff > 5)
		return 0xFF1DDB16;
	if (diff < -5)
		return diff < -10 ? 0xFFFF0000 : 0xFFFF9436;
	return 0xFFEAEAEA;
}

extern std::string GetName(DWORD obj);

// UYARI GİDERİLDİ (C4100): 'obj' parametresi kullanılmadığı için yoruma alındı.
void Kalinlastir(DWORD /*obj*/)
{
	//if(obj) SetNameString(obj, GetName(obj), *(DWORD*)(obj + 0x6A0), 0);   //Nick kalinlastirma
}
//nxwile NPC RENK DEĞİŞTİRME SİSTEMİ NEW
ULONGLONG UNIXTIME2 = GetTickCount64(); // UYARI GİDERİLDİ: int yerine ULONGLONG
int r = 0, g = 255, b = 0; // İSTEK YERİNE GETİRİLDİ: Başlangıç rengi Yeşil yapıldı.
int delta = 5; // Renk değişim hızı
ULONGLONG lastColorChangeTime = 0; // Renk değişim süresi için zaman kontrolü

void UpdateColor()
{
	// RGB -> R -> G -> B döngüsü
	if (r > 0 && b == 0)
	{
		r -= delta;
		g += delta;
	}
	if (g > 0 && r == 0)
	{
		g -= delta;
		b += delta;
	}
	if (b > 0 && g == 0)
	{
		b -= delta;
		r += delta;
	}

	// RGB değerlerini sınırlar içinde tut (0-255)
	if (r < 0) r = 0;
	if (r > 255) r = 255;

	if (g < 0) g = 0;
	if (g > 255) g = 255;

	if (b < 0) b = 0;
	if (b > 255) b = 255;
}
void UpdateColorPeriodically()
{
	// Görsel renk değiştirme (RGB/Yanıp sönme) efekti kapatıldı.
	/*
	UNIXTIME2 = GetTickCount64();

	if (UNIXTIME2 - lastColorChangeTime > 0.1 * SECOND)
	{
		UpdateColor();
		lastColorChangeTime = UNIXTIME2;
	}
	*/
}

void __fastcall Object_Mob_Callback(DWORD obj)
{
	if (!obj) return;
	uint16 protoID = *(uint16*)(obj + KO_SSID);
	string MobID = "";
	uint8 authority = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_WH);
	int16 id = *(int16*)(obj + KO_OFF_ID);
	uint8 nation = *(uint8*)(obj + KO_OFF_NATION);

	Kalinlastir(obj);

	if (id < NPC_BAND)
		return;

	// uint8 myLvl = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_OFF_LEVEL);
	// uint8 lvl = *(uint8*)(obj + KO_OFF_LEVEL);

	// UYARI GİDERİLDİ (C4189): 'color', 'myLvl' ve 'lvl' değişkenleri kullanılmadığı için yoruma alındı.
	// DWORD color = GetLevelColor(myLvl - lvl);

	std::string strObjName = GetName(obj); // UYARI GİDERİLDİ: 'name' -> 'strObjName'

	UpdateColorPeriodically();

	if (IsAntiAFK2(obj))
		SetInfoString(obj, xorstr("Anti AFK"), D3DCOLOR_ARGB(255, 0, 255, 0), 0);

	if (authority == 0 && protoID)
	{
		if (nation != 0 && protoID != 19067 && protoID != 19068 && protoID != 19069 && protoID != 19070 && protoID != 19071 && protoID != 19072)
			SetNameString(obj, GetName(obj) + " (" + to_string(*(uint8*)(obj + KO_OFF_LEVEL)) + ")", *(DWORD*)(obj + 0x738), 0);

		if (IsAntiAFK2(obj))
		{
			MobID = string_format("Anti AFK [ID : %d]", protoID);
		}
		else
		{
			MobID = string_format("[ID(%d) : SID(%d) : TYPE(0)]", id, protoID);
		}


		SetInfoString(obj, MobID, D3DCOLOR_ARGB(255, r, g, b), 0);
	}
}

bool isGM = false;

struct PartyUser {
	USHORT Id;
	USHORT Hp;
	USHORT MaxHp;
	USHORT Mp;
	USHORT MaxMp;
	USHORT Class;
	USHORT Level;
	bool Curse;
	bool Disease;
};

vector<PartyUser> partyMember;
bool partyInit = false;
bool amIInParty = false;
bool waitingForParty = false;
void __fastcall Object_Player_Callback(DWORD obj)
{
	if (!obj) return;
	if (Engine->m_UiMgr->uiMerchantEye != NULL && Engine->m_UiMgr->uiMerchantEye->IsVisible())
		return;

	DWORD myCharBase = *(DWORD*)KO_PTR_CHR;
	if (!myCharBase) return;

	uint8 authority = *(uint8*)(obj + KO_WH);

	// UYARI GİDERİLDİ (C4189): Aşağıdaki kullanılmayan değişkenler yoruma alındı.
	// uint8 Level = *(uint8*)(obj + KO_OFF_LEVEL);
	int16 id = *(int16*)(obj + KO_OFF_ID);
	// uint8 nation = *(uint8*)(obj + KO_OFF_NATION);
	// uint8 nationm = *(uint8*)(myCharBase + KO_OFF_NATION);

	uint8 myAuthority = *(uint8*)(myCharBase + KO_WH);

	if (id > NPC_BAND)
		return;

	std::string playerName = GetName(obj);
	std::string myName = GetName(myCharBase);
	std::string displayString = playerName;

#if (HOOK_SOURCE_VERSION == 1098)
	// UYARI GİDERİLDİ: Sadece 1098'de çalışan bu satırlar makro bloğuna taşındı (C4189)
	bool dusmanMi = (nation != nationm);
	bool isMe = (playerName == myName);
	bool inParty = (Engine->uiPartyBBS != NULL && Engine->uiPartyBBS->PartyFind(id));

	if (!isMe && myAuthority == 0) {
		displayString += " (" + std::to_string(Level) + ")";
	}

	if (isMe)
	{
		if (inParty) SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 255, 255, 0), 0);
		else if (Level < 30) SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 255, 255, 255), 0);
		else SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 100, 210, 255), 0);
	}
	else
	{
		if (inParty) SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 255, 255, 0), 0);
		else if (Level < 30) SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 255, 255, 255), 0);
		else
		{
			if (dusmanMi) SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 255, 128, 128), 0);
			else SetNameString(obj, displayString, D3DCOLOR_ARGB(255, 128, 128, 255), 0);
		}
	}
#endif

	// ... (Kalan kısımlar aynı)

	// OPTİMİZASYON 2: Mutex Lock daraltıldı.
	// Tüm işlemler bitene kadar ana thread'i kitlemesine gerek yok, sadece Map'ten okuyup bırakmalı.
	bool hasTag = false;
	tagName tag;

	Engine->tagLock.lock();
	auto itr = Engine->tagList.find(id);
	if (itr != Engine->tagList.end())
	{
		tag = itr->second;
		hasTag = true;
	}
	Engine->tagLock.unlock();

	if (hasTag && tag.tag.length() > 1)
	{
		SetInfoString(obj, tag.tag, D3DCOLOR_ARGB(255, tag.r, tag.g, tag.b), 0);
	}

	if (authority == 0 && *(uint8*)(obj + 0x7AC) == 3)
	{
		*(uint8*)(obj + 0x7AC) = 0;
		*(uint8*)(obj + KO_WH) = 1;
		return;
	}

	// OPTİMİZASYON 3: Gereksiz For döngüsü silindi!
	// Stringin her karakteri için "SetNameString" basan ve oyunu anlık donduran mantık yerine,
	// Global RGB değerleriyle doğrudan ismi basıyoruz.
	switch (authority)
	{
	case 0:
		// Not: Orijinal kodunda "authority == 0" case'i içindeyken "Eğer benim yetkim 0 değilse (GM'ysem)" diye kontrol etmişsin. 
		// Mantığını bozmadan performans kısmını düzelttim.
		if (myAuthority != 0)
		{
			std::string gmName = "[ADMIN] " + playerName;

			// DİKKAT: UpdateColorPeriodically() fonksiyonunu buradan tamamen SİLDİM!
			// Bu fonksiyon her karakter için çağırılmaz. 'Pearl Engine.cpp' içindeki 
			// 'myTick()' fonksiyonunun başına koymalısın ki renk saniyede/frame'de 1 kere global değişsin.

			SetNameString(obj, gmName, D3DCOLOR_ARGB(255, r, g, b), 0);
			SetInfoString(obj, xorstr("[GAME MASTER]"), D3DCOLOR_ARGB(255, r, g, b), 0);
		}
		break;
	}
}



void __declspec(naked) hkObjectMobLoop()
{
	__asm {
		mov eax, [ecx]
		mov edx, [eax + 0xC]
		pushad
		pushfd
		call Object_Mob_Callback
		popfd
		popad
		jmp KO_FNC_OBJECT_MOB_LOOP_RET
	}
}

void __declspec(naked) hkObjectPlayerLoop()
{
	__asm {
		pushad
		pushfd
		mov ecx, ebx
		call Object_Player_Callback
		popfd
		popad
		jmp KO_FNC_OBJECT_PLAYER_LOOP_ORG
	}
}


// KO Tick fonksiyonu (sürekli çalisir)
const DWORD KO_GAME_TICK = 0x411740;// 0x00410C10;
DWORD TICK_ORG = 0;

const DWORD OFF_PT = 0x344;
const DWORD OFF_PTCOUNT = 0x348;
const DWORD OFF_PTBASE = 0x238;

__inline DWORD RDWORD(DWORD ulBase)
{
	if (ulBase < 0x00AFFFFF) return 0;
	__try { return *(DWORD*)(ulBase); }
	__except (EXCEPTION_EXECUTE_HANDLER) { return 0; }
}

const WORD KO_OFF_INV1 = 0x204; // 2369
const WORD KO_OFF_INV2 = 0x230; // 2369

DWORD InvItemId(int slot) {
	if (Engine->uiInventoryPlug)
	{
		if (DWORD inv = Engine->uiInventoryPlug->m_dVTableAddr)
		{
			if (DWORD itemBase = RDWORD(inv + KO_OFF_INV2 + (4 * slot)))
			{
				if (DWORD extBase = RDWORD(itemBase + 0x6C))
				{
					DWORD ID = RDWORD(RDWORD(itemBase + 0x68));   //infinityarrow
					DWORD EXT = RDWORD(extBase);  //infinityarrow
					return ID + EXT;
				}
			}
		}
	}
	return 0;
}

bool PearlEngine::HasItem(DWORD itemid) {
	for (int x = 14; x < 42; x++) {
		if (InvItemId(x) == itemid) return true;
	}
	return false;
}

time_t arrowKontrol = 0;
time_t timeLapse = 0, guardCheck = 0;

time_t inv_animtime = 0;

std::vector<CSpell*> archerSpells;
std::vector<CSpell*> cureSpells;
std::vector<CSpell*> stoneSpells;
extern TABLE_MOB* GetMobBase(DWORD MobID);

typedef char(__thiscall* tsub_763350)(DWORD ecx, int a2, int a3, int a4, int a5, int a6);
tsub_763350 sub_763350 = (tsub_763350)0x763350;

bool isChicken = false;

void __fastcall civcivVer()
{

}
void __declspec(naked) hkRankImage()
{
	__asm {
		mov al, isChicken
		movzx eax, al
		test eax, eax
		// UYARI GİDERİLDİ: civcivle etiketi kullanılmadığı için silindi (C4102)
	}
}
bool InifinityArrow = false;
static bool spellsloaded = false;
void __fastcall myTick()
{
	if (timeLapse > clock() - 30)
		return;

	timeLapse = clock();

	if (guardCheck < clock() - 200)
	{
		guardCheck = clock();
		if (!Engine->fncGuard.Check())
		{
			raise(SIGSEGV);
		}
	}

	*(float*)0xDFCBB8 = 1.0f / 999.0f;																	// -------------------- fps limiti kaldirma

	if (DWORD target = Engine->GetTarget()) {
		if (*(uint16*)(target + KO_OFF_ID) >= NPC_BAND) {
			uint8 myLvl = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_OFF_LEVEL);
			uint8 lvl = *(uint8*)(target + KO_OFF_LEVEL);
			uint8 nation = *(uint8*)(target + KO_OFF_NATION);
			uint16 protoID = *(uint16*)(target + KO_SSID);
			DWORD color = GetLevelColor(myLvl - lvl);
			std::string targetName = GetName(target); // UYARI GİDERİLDİ: 'name' -> 'targetName'
			if (Engine->uiTargetBar && nation == 0
				&& protoID != 19067 && protoID != 19068 && protoID != 19069 && protoID != 19070 && protoID != 19071 && protoID != 19072)
				Engine->uiTargetBar->SetInfo(color, lvl, targetName); // Değişken güncellendi
		}
	}
	// (Fonksiyonun devamı)
	//animasyon start
	if (*(DWORD*)KO_PTR_CHR)
	{
		if (Engine->m_PlayerBase)
			Engine->m_PlayerBase->m_iZoneID = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_OFF_ZONE);

		// UYARI GİDERİLDİ: GetTickCount64() (işaretsiz) ile inv_animtime (işaretli) karşılaştırmasındaki 
		// uyuşmazlığı çözmek için inv_animtime değişkenini (ULONGLONG) türüne cast ettik.
		if (Engine->uiInventoryPlug
			&& GetTickCount64() > (ULONGLONG)inv_animtime
			&& Engine->IsVisible(Engine->uiInventoryPlug->m_dVTableAddr))
		{
			DWORD chr = *(DWORD*)KO_PTR_CHR + KO_OFF_N3CHR;
			if (chr)
				__ChrAniCurSet(chr, *(int*)(*(DWORD*)KO_PTR_CHR + KO_OFF_ANIM_ID), false, 1.175494351e-38F, 0, true);
			inv_animtime = GetTickCount64() + 200;
		}

		// HATA DÜZELTİLDİ: Süslü parantez eklendi. Aşağıdaki Infinity kodları artık bu döngünün kurbanı olmayacak.
		for (auto a : Engine->privatemessages) {
			a->Tick();
		}

		//animasyon end----------------------------------



		 //infinity arrow
		if (arrowKontrol < clock() - 2000)
		{
			arrowKontrol = clock();
			if (Engine->uiInventoryPlug)
			{
				if (DWORD inv = Engine->uiInventoryPlug->m_dVTableAddr)
				{
					if (!spellsloaded)
					{
						spellsloaded = true;
						archerSpells.clear();
						cureSpells.clear();
						stoneSpells.clear();

						for (uint32 i = 102003; i <= 288566; i++)
						{
							if (CSpell* spell = GetSkillBase(i)) {
								if (spell->dwNeedItem == 391010000)
									archerSpells.push_back(spell);
							}
						}

						std::map<uint32, CSpell>::iterator itr;
						for (itr = Engine->skillmap.begin(); itr != Engine->skillmap.end(); itr++)
						{
							if (CSpell* spell = GetSkillBase(itr->second.dwID))
							{
								if (spell->dwNeedItem == 379062000
									|| spell->dwNeedItem == 379059000
									|| spell->dwNeedItem == 379060000
									|| spell->dwNeedItem == 379061000)
									stoneSpells.push_back(spell);
							}
						}
						uint32 cureIDs[] = { 107736, 108736, 207736, 208736 };
						for (int i = 0; i < 4; i++) {
							if (CSpell* spell = GetSkillBase(cureIDs[i])) cureSpells.push_back(spell);
						}
					}
					// OPTİMİZASYON: Her eşya için bir kez HasItem kontrolü yap.
					bool hasRogueStone = Engine->HasItem(479060000);
					bool hasMageStone = Engine->HasItem(479061000);
					bool hasPriestStone = Engine->HasItem(479062000);
					bool hasWarriorStone = Engine->HasItem(479059000);
					bool hasInfCure = Engine->HasItem(346391000);
					bool hasInfArrow = Engine->HasItem(800606000);

					// ==========================================
					// 1. Infinity Stone Of Rogue
					// ==========================================
					if (hasRogueStone && !StoneOfRogue)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 379060000 || (s->dwNeedItem == 0 && s->dwID / 10000 == 108) || (s->dwNeedItem == 0 && s->dwID / 10000 == 208)) {
								s->dwNeedItem = 479060000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								if (itcrc != Engine->skillcrc.end()) {
									// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
									itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
								}
							}
						}
						// Bulunan Gerçek Rogue Adresleri
						*(DWORD*)(0x0067FF16 + 1) = 479060000; *(DWORD*)(0x00682EEF + 1) = 479060000;
						*(DWORD*)(0x009531C6 + 1) = 479060000; *(DWORD*)(0x009531FD + 1) = 479060000;
						*(DWORD*)(0x0095321C + 1) = 479060000; *(DWORD*)(0x009552A1 + 1) = 479060000;
						*(DWORD*)(0x009552DF + 1) = 479060000; *(DWORD*)(0x00955342 + 1) = 479060000;
						StoneOfRogue = true;
					}
					else if (!hasRogueStone && StoneOfRogue)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 479060000) {
								s->dwNeedItem = 379060000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								if (itcrc != Engine->skillcrc.end()) {
									// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
									itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
								}
							}
						}
						*(DWORD*)(0x0067FF16 + 1) = 379060000; *(DWORD*)(0x00682EEF + 1) = 379060000;
						*(DWORD*)(0x009531C6 + 1) = 379060000; *(DWORD*)(0x009531FD + 1) = 379060000;
						*(DWORD*)(0x0095321C + 1) = 379060000; *(DWORD*)(0x009552A1 + 1) = 379060000;
						*(DWORD*)(0x009552DF + 1) = 379060000; *(DWORD*)(0x00955342 + 1) = 379060000;
						StoneOfRogue = false;
					}

					// ==========================================
					// 2. Infinity Stone Of Mage
					// ==========================================
					if (hasMageStone && !StoneOfMage)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 379061000 || (s->dwNeedItem == 0 && s->dwID / 10000 == 109) || (s->dwNeedItem == 0 && s->dwID / 10000 == 209) || (s->dwNeedItem == 0 && s->dwID / 10000 == 110) || (s->dwNeedItem == 0 && s->dwID / 10000 == 210)) {
								s->dwNeedItem = 479061000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						// Bulunan Gerçek Mage Adresleri
						*(DWORD*)(0x0067FF6E + 1) = 479061000; *(DWORD*)(0x00682F47 + 1) = 479061000;
						*(DWORD*)(0x00953240 + 1) = 479061000; *(DWORD*)(0x00953277 + 1) = 479061000;
						*(DWORD*)(0x00953296 + 1) = 479061000; *(DWORD*)(0x0095535F + 1) = 479061000;
						*(DWORD*)(0x0095539D + 1) = 479061000; *(DWORD*)(0x00955400 + 1) = 479061000;
						StoneOfMage = true;
					}
					else if (!hasMageStone && StoneOfMage)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 479061000) {
								s->dwNeedItem = 379061000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						*(DWORD*)(0x0067FF6E + 1) = 379061000; *(DWORD*)(0x00682F47 + 1) = 379061000;
						*(DWORD*)(0x00953240 + 1) = 379061000; *(DWORD*)(0x00953277 + 1) = 379061000;
						*(DWORD*)(0x00953296 + 1) = 379061000; *(DWORD*)(0x0095535F + 1) = 379061000;
						*(DWORD*)(0x0095539D + 1) = 379061000; *(DWORD*)(0x00955400 + 1) = 379061000;
						StoneOfMage = false;
					}

					// ==========================================
					// 3. Infinity Stone Of Priest
					// ==========================================
					if (hasPriestStone && !StoneOfPriest)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 379062000 || (s->dwNeedItem == 0 && s->dwID / 10000 == 111) || (s->dwNeedItem == 0 && s->dwID / 10000 == 211) || (s->dwNeedItem == 0 && s->dwID / 10000 == 112) || (s->dwNeedItem == 0 && s->dwID / 10000 == 212)) {
								s->dwNeedItem = 479062000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						// Bulunan Gerçek Priest Adresleri
						*(DWORD*)(0x0067FFC6 + 1) = 479062000; *(DWORD*)(0x00682F9F + 1) = 479062000;
						*(DWORD*)(0x009532BA + 1) = 479062000; *(DWORD*)(0x009532F1 + 1) = 479062000;
						*(DWORD*)(0x00953310 + 1) = 479062000; *(DWORD*)(0x0095541D + 1) = 479062000;
						*(DWORD*)(0x00955453 + 1) = 479062000; *(DWORD*)(0x00955499 + 1) = 479062000;
						StoneOfPriest = true;
					}
					else if (!hasPriestStone && StoneOfPriest)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 479062000) {
								s->dwNeedItem = 379062000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						*(DWORD*)(0x0067FFC6 + 1) = 379062000; *(DWORD*)(0x00682F9F + 1) = 379062000;
						*(DWORD*)(0x009532BA + 1) = 379062000; *(DWORD*)(0x009532F1 + 1) = 379062000;
						*(DWORD*)(0x00953310 + 1) = 379062000; *(DWORD*)(0x0095541D + 1) = 379062000;
						*(DWORD*)(0x00955453 + 1) = 379062000; *(DWORD*)(0x00955499 + 1) = 379062000;
						StoneOfPriest = false;
					}

					// ==========================================
					// 4. Infinity Stone Of Warrior
					// ==========================================
					if (hasWarriorStone && !StoneOfWarrior)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 379059000 || (s->dwNeedItem == 0 && s->dwID / 10000 == 105) || (s->dwNeedItem == 0 && s->dwID / 10000 == 205) || (s->dwNeedItem == 0 && s->dwID / 10000 == 106) || (s->dwNeedItem == 0 && s->dwID / 10000 == 206)) {
								s->dwNeedItem = 479059000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						// Warrior Adresleri zaten doğruydu
						*(DWORD*)(0x0067FEBE + 1) = 479059000; *(DWORD*)(0x00682E97 + 1) = 479059000;
						*(DWORD*)(0x00953027 + 1) = 479059000; *(DWORD*)(0x0095306A + 1) = 479059000;
						*(DWORD*)(0x009531A2 + 1) = 479059000; *(DWORD*)(0x009551E3 + 1) = 479059000;
						*(DWORD*)(0x00955221 + 1) = 479059000; *(DWORD*)(0x00955284 + 1) = 479059000;
						StoneOfWarrior = true;
					}
					else if (!hasWarriorStone && StoneOfWarrior)
					{
						for (auto& s : stoneSpells) {
							if (s->dwNeedItem == 479059000) {
								s->dwNeedItem = 379059000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						*(DWORD*)(0x0067FEBE + 1) = 379059000; *(DWORD*)(0x00682E97 + 1) = 379059000;
						*(DWORD*)(0x00953027 + 1) = 379059000; *(DWORD*)(0x0095306A + 1) = 379059000;
						*(DWORD*)(0x009531A2 + 1) = 379059000; *(DWORD*)(0x009551E3 + 1) = 379059000;
						*(DWORD*)(0x00955221 + 1) = 379059000; *(DWORD*)(0x00955284 + 1) = 379059000;
						StoneOfWarrior = false;
					}

					// ==========================================
					// 5. Infinity Cure
					// ==========================================
					if (hasInfCure && !isActivedCure)
					{
						for (auto& s : cureSpells) {
							if (s->dwNeedItem == 370005000) {
								s->dwNeedItem = 0;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						isActivedCure = true;
					}
					else if (!hasInfCure && isActivedCure)
					{
						for (auto& s : cureSpells) {
							if (s->dwNeedItem == 0) {
								s->dwNeedItem = 370005000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						isActivedCure = false;
					}

					// ==========================================
					// 6. Infinity Arrow
					// ==========================================
					if (hasInfArrow && !isActivedArrow)
					{
						for (auto& s : archerSpells) {
							if (s->dwNeedItem == 391010000) {
								s->dwNeedItem = 0;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						isActivedArrow = true;
					}
					else if (!hasInfArrow && isActivedArrow)
					{
						for (auto& s : archerSpells) {
							if (s->dwNeedItem == 0) {
								s->dwNeedItem = 391010000;
								auto itcrc = Engine->skillcrc.find(s->dwID + 2031);
								// UYARI GİDERİLDİ: -1 değerleri (uint32_t)-1 olarak dönüştürüldü (C4245)
								if (itcrc != Engine->skillcrc.end()) itcrc->second = SpellCRC(crc32((uint8*)(DWORD)s, 0xA8, (uint32_t)-1), crc32((uint8*)((DWORD)s + 0xB4), 0x2C, (uint32_t)-1));
							}
						}
						isActivedArrow = false;
					}
				}
			}
		}
	}
}
DWORD __declspec(naked) hkTick()
{
	__asm {
		pushad
		pushfd
		call myTick
		popfd
		popad
		jmp TICK_ORG
	}
}

DWORD rtOrg = 0;
DWORD rTmp = 0;

DWORD __declspec(naked) hkSetFontString()
{
	__asm {
		pushad
		pushfd
		mov rTmp, ecx
	}
	if (RDWORD(rTmp + 0x1C) == 0)
	{
		__asm {
			popfd
			popad
			xor eax, eax
			ret 8
		}
	}
	__asm {
		popfd
		popad
		jmp rtOrg
	}
}

#if (HOOK_SOURCE_VERSION == 1098)
// minimap harita pozisyon ayarlari
const int upY = 5;
const int upX = 17;

void __declspec(naked) hkMinimapPos()
{
	__asm {
		add edx, upY
		add eax, upX
		push edx
		push eax
		mov eax, [ESI + 0x2C]
		call eax
		pop edi
		pop esi
		pop ebp
		pop ebx
		add esp, 0x38
		ret
	}
}
#endif
DWORD PearlEngine::KOGetTarget()
{
	// UYARI GİDERİLDİ (C4459): 'KO_ADR' global değişkeniyle çakışmaması için 'loc_KO_ADR' olarak değiştirildi.
	DWORD loc_KO_ADR = *(DWORD*)KO_PTR_CHR;
	// UYARI GİDERİLDİ: Açıkça (uint16) türüne dönüştürüldü.
	uint16 targetID = (uint16)(*(DWORD*)(loc_KO_ADR + KO_OFF_MOB));
	if (targetID >= NPC_BAND)
	{
		Func_GetObjectBase = (tGetObjectBase)KO_FMBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, targetID, 1);
	}
	else {
		Func_GetObjectBase = (tGetObjectBase)KO_FPBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, targetID, 1);
	}
}
size_t findCaseInsensitive(std::string data, std::string toSearch)
{
	if (data.empty() || toSearch.empty())
		return std::string::npos;

	// UYARI GİDERİLDİ (C4244): ::tolower lambda ile char tipine açıkça cast edildi.
	std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c) -> char { return (char)std::tolower(c); });
	std::transform(toSearch.begin(), toSearch.end(), toSearch.begin(), [](unsigned char c) -> char { return (char)std::tolower(c); });

	return data.find(toSearch, 0);
}
const DWORD KO_AUTO_ATTACK = 0x0054B2DA;
const DWORD KO_ZONE_LOAD_TERRAIN = 0x00972C63;
const DWORD KO_ZONE_LOAD_TERRAIN_KEEP = 0x00972C80;
DWORD KO_ZONE_LOAD_TERRAIN_ORG = 0;

std::list<std::string> oldMapList_GTD = {

	"battlezone_f.gtd",
	//"freezone_a_event2012.gtd"
	//"freezone_b_2012event.gtd",
	"In_dungeon06.gtd",
	"xmas_battle.gtd",
	"Old_Karus.gtd",
	"Old_Elmo.gtd",
	"2017_flagwar.gtd",
	"Worldwar.gtd",
	"FreeZone_bb.gtd",
	"FreeZone.gtd",
#if (HOOK_SOURCE_VERSION == 1098)
	"moradon_xmas.gtd",
	"war_a.gtd",
#endif
};

bool __fastcall IsOldMap(const std::string& gtd)
{
	const std::string tmpGtd = gtd;
	auto it = std::find_if(oldMapList_GTD.begin(), oldMapList_GTD.end(), [&](const std::string& v) {  return findCaseInsensitive(tmpGtd, v) != string::npos; });
	return it != oldMapList_GTD.end();
}

void __declspec(naked) hkLoadTerrainData()
{
	__asm {
		pushad
		pushfd
		mov ecx, esi
		add ecx, 0x24
		call IsOldMap
		movzx eax, al
		test eax, eax
		jne okuma
		mov ecx, DWORD PTR DS : [KO_PTR_CHR]
		mov ecx, [ecx + KO_OFF_ZONE]
		cmp ecx, 0x70 // Harita zonesi hex kodu yazilacak.
		je okuma
		popfd
		popad
		jmp KO_ZONE_LOAD_TERRAIN_ORG
		okuma :
		popfd
			popad
			jmp KO_ZONE_LOAD_TERRAIN_KEEP
	}
}

bool __genieAttackBlock = true;

bool __fastcall RAttack(DWORD caller = NULL)
{
	if (caller && caller >= 0xc90acc && !IsBadReadPtr((void*)caller, sizeof(DWORD)))
		return __genieAttackBlock && *(DWORD*)caller == 0xc90acc;  // Genie R atack buton kodu
	return false;
}

void __declspec(naked) hkAttack()
{
	__asm {
		mov esi, 0xFFFE
		mov edx, [ESP]
		pushad
		pushfd
		mov ecx, edx
		call RAttack
		movzx eax, al
		test eax, eax
		jne engeller
		popfd
		popad
		mov edx, KO_AUTO_ATTACK
		add edx, 5
		push edx
		ret
		engeller :
		popfd
			popad
			pop edi
			xor al, al
			pop esi
			ret
	}
}

// UYARI GİDERİLDİ (C4100): 'edx' başvurulmayan parametre uyarısı için yoruma alındı.
void __fastcall hkDisableVisible(DWORD ecx, DWORD /*edx*/, bool a)
{
	a = false;
	*(DWORD*)(ecx + 0x10D) = a;
}

const DWORD KO_SKILLBAR_KEY_INPUT = 0x0067CE10;
const DWORD KO_SKILLBAR_KEY_INPUT_BLOCK = 0x0067CE1C;
DWORD KO_SKILLBAR_KEY_INPUT_KEEP = NULL;
DWORD KO_SKILLBAR_SHORTCUT_KEEP = 0x0050E295;
DWORD KO_SKILLBAR_MOUSE_INPUT_KEEP = 0x0067A739;
const DWORD KO_SKILLBAR_SHORTCUT_INPUT = 0x0050E290;
const DWORD KO_SKILLBAR_SHORTCUT_BLOCK = 0x0050E29E;
const DWORD KO_SKILLBAR_MOUSE_INPUT = 0x0067A734; // EDX
const DWORD KO_SKILLBAR_MOUSE_INPUT_BLOCK = 0x0067A7AD;

static bool IsGameWindowFocused()
{
	HWND hWnd = GetForegroundWindow();
	if (!hWnd)
		return false;

	DWORD activePid = 0;
	GetWindowThreadProcessId(hWnd, &activePid);
	return activePid == GetCurrentProcessId();
}

struct OverlayEnumData
{
	std::vector<std::string> matches;
};

static BOOL CALLBACK EnumOverlayWindowsProc(HWND hwnd, LPARAM lParam)
{
	if (!hwnd || !IsWindowVisible(hwnd))
		return TRUE;

	char className[256] = { 0 };
	char title[256] = { 0 };
	GetClassNameA(hwnd, className, sizeof(className));
	GetWindowTextA(hwnd, title, sizeof(title));

	if (std::strlen(className) == 0)
		return TRUE;

	auto* p = reinterpret_cast<OverlayEnumData*>(lParam);
	std::string cls = className;
	std::transform(cls.begin(), cls.end(), cls.begin(), [](unsigned char c) { return static_cast<char>(std::toupper(c)); });

	for (const auto& suspicious : { "AUTOIT V3 GUI", "AUTOIT V3", "PROCESSHACKER", "PROC MON WINDOW CLASS", "OLLYDBG", "WINDBGFRAMECLASS", "TFORMRAMOPEN.UNICODECLASS", "TMEMORYBROWSER", "TFOUNDCODEDIALOG", "THUNDERRT6FORMDC", "TFORM1", "AFX:400000:8:10011:0:20575" })
	{
		if (cls.find(suspicious) != std::string::npos || std::string(title).find("Cheat Engine") != std::string::npos)
		{
			p->matches.push_back(std::string(title));
			return FALSE;
		}
	}

	return TRUE;
}

static bool IsSuspiciousOverlayVisible()
{
	OverlayEnumData data;
	EnumWindows(EnumOverlayWindowsProc, reinterpret_cast<LPARAM>(&data));
	return !data.matches.empty();
}

static void LogAntiCheatEvent(const char* reason)
{
	OutputDebugStringA(reason);
}

static bool TriggerSuspiciousAction(const char* reason)
{
	static DWORD suspiciousCount = 0;
	static ULONGLONG lastTriggerTick = 0;
	ULONGLONG now = GetTickCount64();

	LogAntiCheatEvent(reason);

	if (lastTriggerTick != 0 && (now - lastTriggerTick) < 5000)
		++suspiciousCount;
	else
		suspiciousCount = 1;

	lastTriggerTick = now;

	if (suspiciousCount >= 4)
	{
		Shutdown(reason);
		return true;
	}

	return false;
}

static bool CheckCombatPatternAnomaly(DWORD key)
{
	static DWORD lastPatternKey = 0;
	static ULONGLONG lastPatternTick = 0;
	static uint32_t patternBurst = 0;
	ULONGLONG now = GetTickCount64();

	if (lastPatternKey == key && lastPatternTick != 0 && (now - lastPatternTick) < 90)
	{
		patternBurst++;
		if (patternBurst >= 12)
			return TriggerSuspiciousAction("Combat pattern anomaly detected.");
	}
	else
	{
		patternBurst = 0;
	}

	lastPatternKey = key;
	lastPatternTick = now;
	return false;
}

bool __fastcall MacroEngels()
{
	if (!IsGameWindowFocused())
		return TriggerSuspiciousAction("Macro / focus violation detected.");

	if (IsSuspiciousOverlayVisible())
		return TriggerSuspiciousAction("Suspicious overlay / screen macro detected.");

	if (CheckCombatPatternAnomaly(0xA5A5A5A5))
		return true;

	static ULONGLONG lastMacroTick = 0;
	static uint32_t macroBurst = 0;
	ULONGLONG now = GetTickCount64();

	if (lastMacroTick != 0 && (now - lastMacroTick) < 35)
	{
		macroBurst++;
		if (macroBurst >= 15)
			return TriggerSuspiciousAction("Illegal macro burst detected.");
	}
	else
	{
		macroBurst = 0;
	}

	lastMacroTick = now;
	return false;
}

void __declspec(naked) hkSkillbarShortcutInput()
{
	__asm {
		pushad
		pushfd
		call MacroEngels
		movzx eax, al
		test eax, eax
		jne engellez
		popfd
		popad
		mov eax, [0xF50FE0] //2369
		jmp KO_SKILLBAR_SHORTCUT_KEEP
		engellez :
		popfd
			popad
			jmp KO_SKILLBAR_SHORTCUT_BLOCK
	}
}

void __declspec(naked) hkSkillbarMouseInput()
{
	__asm {
		pushad
		pushfd
		call MacroEngels
		movzx eax, al
		test eax, eax
		jne engellex
		popfd
		popad
		mov eax, 0x004D3C30 // 2369
		call eax
		jmp KO_SKILLBAR_MOUSE_INPUT_KEEP
		engellex :
		popfd
			popad
			jmp KO_SKILLBAR_MOUSE_INPUT_BLOCK
	}
}

// UYARI GİDERİLDİ (C4100): 'key' başvurulmayan parametre uyarısı için yoruma alındı.
bool __fastcall SkillKeyCheck(DWORD key)
{
	if (Engine != nullptr && Engine->m_isGenieStatus)
		return true;

	if (!IsGameWindowFocused())
		return TriggerSuspiciousAction("Background skill input detected.");

	if (CheckCombatPatternAnomaly(key))
		return true;

	static DWORD lastSkillKey = 0;
	static ULONGLONG lastSkillTick = 0;
	static uint32_t skillBurst = 0;
	ULONGLONG now = GetTickCount64();

	if (key == lastSkillKey && lastSkillTick != 0 && (now - lastSkillTick) < 80)
	{
		skillBurst++;
		if (skillBurst >= 8)
			return TriggerSuspiciousAction("Skill spam / macro abuse detected.");
	}
	else
	{
		skillBurst = 0;
	}

	lastSkillKey = key;
	lastSkillTick = now;
	return false;
}

void __declspec(naked) hkSkillbarKeyInput()
{
	__asm {
		pushad
		pushfd
		mov ecx, edi
		call SkillKeyCheck
		movzx eax, al
		test eax, eax
		jne engelle
		popfd
		popad
		jmp KO_SKILLBAR_KEY_INPUT_KEEP
		engelle :
		popfd
			popad
			jmp KO_SKILLBAR_KEY_INPUT_BLOCK
	}
}


DWORD KO_SET_EVENTNOTICE_POS = 0x0082A572;
DWORD KO_SET_EVENTNOTICE_POS_ORG = 0;

void __fastcall Ayarlamk(DWORD efx)
{
	Engine->hkServerNotice = efx;
	koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
	POINT pt;
	Engine->GetUiPos(efx, pt);
#if 0
#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)	// 1098 & 1534 vGenie pozisyon ayarlaması Militarycamp ve premiumlar
	LONG isPost = 63;
	if (g_pMain->uiGenieSubPlug != NULL)
	{
		if (g_pMain->IsVisible(g_pMain->uiGenieSubPlug->TargetSam))
			isPost = 115;
		else if (g_pMain->IsVisible(g_pMain->uiGenieSubPlug->TargetTwo))
			isPost = 89;
#else		// 2369 Genie pozisyon ayarlaması Militarycamp ve premiumlar
	LONG isPost = 69;
	if (g_pMain->uiGenieSubPlug != NULL)
	{
		if (g_pMain->IsVisible(g_pMain->uiGenieSubPlug->TargetSam))
			isPost = 117;
		else if (g_pMain->IsVisible(g_pMain->uiGenieSubPlug->TargetTwo))
			isPost = 93;
#endif
		if (g_pMain->IsVisible(g_pMain->hkCampAdress))
			isPost += 23;

		pt.y = isPost;
		g_pMain->SetUIPos(efx, pt);
		if (g_pMain->IsVisible(g_pMain->hkCampAdress))
		{
			g_pMain->GetUiPos(g_pMain->hkCampAdress, pt);
			pt.y = LONG(isPost - 23);
			g_pMain->SetUIPos(g_pMain->hkCampAdress, pt);
		}
		POINT zs;
		zs.x = koScreen.x - 187;		//genie sağ base konumu
		zs.y = 0;
		g_pMain->SetUIPos(g_pMain->uiGenieSubPlug->m_dVTableAddr, zs);
	}
#endif
	if (Engine->uiTaskbarMain) Engine->uiTaskbarMain->UpdatePosition();
	}

void __declspec(naked) hkEventNotice()
{
	__asm {
		pushad
		pushfd
		call Ayarlamk
		popfd
		popad
		jmp KO_SET_EVENTNOTICE_POS_ORG
	}
}

DWORD GENIE_ORG = 0x40F7D0;
POINT ptgenie;
int geniex, geniey;

void __declspec(naked) hkGenieSetPos()
{
	__asm {
		pushad
		pushfd
	}
	koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
#if (HOOK_SOURCE_VERSION == 1098 || HOOK_SOURCE_VERSION == 1534)
	geniex = koScreen.x - 170;
#else
	geniex = koScreen.x - 187;
#endif
	geniey = 0;
	__asm {
		popfd
		popad
		mov edx, geniex
		mov[esp + 4], edx
		mov edx, geniey
		mov[esp + 8], edx
		jmp GENIE_ORG
	}
}

#if (HOOK_SOURCE_VERSION == 1098)
DWORD Real_CharacterSelectLeft = 0x004EB560;					// 2369
DWORD Real_CharacterSelectLeft_ORG = 0x004EB560;				// 2369
DWORD Real_CharacterSelectRight = 0x004EB800;					// 2369
DWORD Real_CharacterSelectRight_ORG = 0x004EB800;				// 2369
void __fastcall Hook_CharacterSelectLeft(LPDWORD, LPVOID)
{
	if ((int)(*(DWORD*)(*(DWORD*)(0xF51000) + 0x48C)) != 1)		// 2369
	{
		__asm
		{
			MOV ECX, DWORD PTR DS : [0x00F51000]				// 2369
			CALL Real_CharacterSelectLeft_ORG
		}
	}
}

void __fastcall Hook_CharacterSelectRight(LPDWORD, LPVOID)
{
	if ((int)(*(DWORD*)(*(DWORD*)(0xF51000) + 0x48C)) != 2)  // 2369
	{
		if ((int)(*(DWORD*)(*(DWORD*)(0xF51000) + 0x48C)) == 0)  // 2369
		{
			(*(DWORD*)(*(DWORD*)(0xF51000) + 0x48C)) = 1;  // 2369
			__asm
			{
				MOV ECX, DWORD PTR DS : [0x00F51000]  // 2369
				CALL Real_CharacterSelectLeft_ORG
			}
		}
		else
		{
			__asm
			{
				MOV ECX, DWORD PTR DS : [0x00F51000]  // 2369
				CALL Real_CharacterSelectRight_ORG
			}
		}
	}
}
#endif
typedef bool (WINAPI* tUIOnKeyPress)(int iKey);
bool WINAPI hkUIOnKeyPress(int iKey)
{
	static int i = 0;
	if (iKey == DIK_RETURN || iKey == DIK_NUMPADENTER) {
		i++;

		// UYARI GİDERİLDİ (C4459): 'r' değişken ismi global r (RGB) ile çakıştığı için 'bResult' yapıldı.
		bool bResult = false;

		// UYARI VE ÇÖKME GİDERİLDİ: Tüm null kontrolleri yapıldıktan sonra işleme izin veriliyor.
		if (Engine != nullptr && Engine->uiPowerUpStore != nullptr && Engine->IsVisible(Engine->uiPowerUpStore->m_dVTableAddr))
		{
			bResult = true;
			Engine->uiPowerUpStore->ReceiveMessage((DWORD*)Engine->uiPowerUpStore->btn_search, UIMSG_BUTTON_CLICK);
		}
		return bResult;
	}
	else if (iKey == DIK_ESCAPE)
	{
		// UYARI GİDERİLDİ: Engine ve uiTagChange null kontrolü eklendi.
		if (Engine != nullptr && Engine->uiTagChange != nullptr && Engine->IsVisible(Engine->uiTagChange->m_dVTableAddr))
			Engine->uiTagChange->Close();
	}
	return false;
}

#define D3DX_PI    ((FLOAT)  3.141592654f)
#define D3DXToRadian( degree ) ((degree) * (D3DX_PI / 180.0f))
#define D3DXToDegree( radian ) ((radian) * (180.0f / D3DX_PI))

const DWORD GetMark = 0x0079E6A8;						// Civciv Sembolü ekleme
constexpr DWORD secondadres2s = 0x0079E6B1;				// Civciv Sembolü ekleme
const DWORD ar = 0x0079E4A0;							// Civciv Sembolü ekleme
bool _fastcall civcivmi(DWORD nPlayerBase, DWORD eax)
{


	if (nPlayerBase == eax)
	{
		uint8 m_iLevel;
		DWORD chr;
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)KO_PTR_CHR, &chr, sizeof(chr), 0);
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)(chr + 0x74C), &m_iLevel, sizeof(m_iLevel), 0);

		if (m_iLevel < 30 && m_iLevel > 0)
			return true;
		else
			return false;
	}

	if (IsBadReadPtr((VOID*)nPlayerBase, sizeof(DWORD)))
		return false;
	uint8 val = *(uint8*)(nPlayerBase + 0x74C);

	if (val < 30 && val > 0)
		return true;

	return false;
}
void __declspec(naked) hkMarkPos()
{
	__asm
	{

		pushad
		pushfd
		mov ecx, esi
		mov edx, eax
		call civcivmi
		movzx eax, al
		test eax, eax
		jne devam
		popfd
		popad

		push 0x18
		push 0x00
		call ar
		jmp secondadres2s
		devam :
		popfd
			popad
			push  0x06
			push  0x00
			call ar
			jmp secondadres2s


	}
}
DWORD KO_MAGIC_SKILL_ANIMATION_ORG = 0;
bool isAttack = true;

void __fastcall hkMagicAnimation()
{
	if (__genieAttackBlock || !(Engine->m_PlayerBase->isWarrior() || Engine->m_PlayerBase->isPriest()))
		return;

	if (DWORD target = Engine->GetTarget()) {
		isAttack = !isAttack;

		// UYARI GİDERİLDİ: 'bool' değişkeni 'DWORD' içerisine alınarak ASM stack boyutu hatası giderildi.
		DWORD dwAttack = isAttack;

		__asm {			// En alt atack buton islevi 01.02.2021
			push target
			push dwAttack
			mov ecx, [KO_DLG]
			mov ecx, [ecx]
			mov eax, 0x00542260
			call eax
		}
	}
}
void __declspec(naked) GetAnimationSkill()
{
	__asm
	{
		pushad
		pushfd
		call hkMagicAnimation
		popfd
		popad
		jmp KO_MAGIC_SKILL_ANIMATION_ORG
	}

}
void __fastcall msga(DWORD esxx)
{

	DWORD tmp = 0;

	Engine->GetChildByID(esxx, std::string("str_mcount"), tmp);
	if (tmp == 0)
		return;
	std::string getString;
	getString = Engine->GetString(tmp).c_str();
	if (!getString.empty())
	{
		int getCount = std::stoi(getString.c_str());
		getCount++;
		Engine->SetString(tmp, string_format("%d", getCount));
	}
	else
		Engine->SetString(tmp, "1");


}

__declspec(naked) void hkPMMessage()
{

	__asm {

		pushad
		pushfd
		mov edx, esi
		call msga
		popfd
		popad
		jmp KO_WHISPER_GETMESSAGE_ORG

	}

}
void __fastcall msgaa(DWORD esxx)
{
	DWORD tmp = 0;

	Engine->GetChildByID(esxx, std::string("str_mcount"), tmp);

	if (tmp > 0)
	{

		Engine->SetString(tmp, "");
	}
}
void __fastcall setVisible(DWORD esxx)
{
	// UYARI GİDERİLDİ (C4189): Kullanılmayan 'tmp' değişkeni silindi.
	DWORD tmp1 = 0;

	Engine->GetChildByID(esxx, std::string("base_default"), tmp1);
	*(DWORD*)(tmp1 + 0x10D) = false;
	Engine->GetChildByID(esxx, std::string("btn_view"), tmp1);

	*(DWORD*)(tmp1 + 0x10D) = false;
	Engine->GetChildByID(esxx, std::string("btn_duel"), tmp1);

	*(DWORD*)(tmp1 + 0x10D) = false;
	Engine->GetChildByID(esxx, std::string("btn_party"), tmp1);
	*(DWORD*)(tmp1 + 0x10D) = false;

	Engine->GetChildByID(esxx, std::string("pus_gift"), tmp1);
	*(DWORD*)(tmp1 + 0x10D) = false;
}

__declspec(naked) void hkPMCreateWindow()
{
	__asm {
		pushad
		pushfd
		cmp ebx, 0
		jne gizle
		mov ecx, ecx
		call setVisible
		popfd
		popad
		jmp KO_WHISPER_CREATE_ORG
		gizle :
		mov ecx, ecx
			call setVisible
			popfd
			popad
			jmp KO_WHISPER_CREATE_ORG
	}
}

__declspec(naked) void hkPMCloseWindow()
{
	__asm {
		pushad
		pushfd
		mov ecx, ecx
		call setVisible
		popfd
		popad
		jmp KO_WHISPER_OPEN_ORG
	}
}

__inline DWORD SaitX(DWORD ulBase)
{
	if (ulBase < 0x00AFFFFF) return 0;
	__try { return *(DWORD*)(ulBase); }
	__except (EXCEPTION_EXECUTE_HANDLER) { return 0; }
}

DWORD pmBase;

void __fastcall setPMRecv(DWORD esxx, uint32_t dwMessage)
{
	if (dwMessage != 5) return;

	// UYARI GİDERİLDİ (C4189): Kullanılmayan 'tmp' değişkeni buradan da silindi.

	std::string elementname = Engine->GetStringElementName(pmBase).c_str();

	// UYARI GİDERİLDİ: Hiç kullanılmayan btn_block, btn_view, btn_party gibi değişkenler tamamen silindi (C4101)

	if (elementname == "btn_view")
	{
		DWORD tmp1 = 0;
		std::string sName;
		Engine->GetChildByID(esxx, std::string("exit_id"), tmp1);
		sName = Engine->GetString(tmp1).c_str();
		Engine->str_replace(sName, " ", "");
		Packet result(WIZ_USER_INFO, uint8(2));
		result.SByte();
		result << sName;
		Engine->Send(&result);
		__asm
		{
			mov ecx, esxx
			call setVisible

		}
		return;
	}
	else if (elementname == "pus_gift")
	{
		if (Engine->uiPowerUpStore != NULL)
		{
			Engine->uiPowerUpStore->UpdateItemList(Engine->m_UiMgr->item_list, Engine->m_UiMgr->cat_list);
			Engine->uiPowerUpStore->UpdateRefundItemList(Engine->m_UiMgr->pusrefund_itemlist);
			Engine->uiPowerUpStore->Open();
		}
		__asm
		{
			mov ecx, esxx
			call setVisible

		}
		return;
	}
	else if (elementname == "btn_party")
	{
		DWORD tmp1 = 0;
		Engine->GetChildByID(esxx, std::string("exit_id"), tmp1);
		std::string partyPlayerName = Engine->GetString(tmp1).c_str(); // UYARI GİDERİLDİ
		DWORD base = SaitX(SaitX(KO_DLG) + 0x238);
		DWORD partyCount = SaitX(base + 0x348);
		Packet result(WIZ_PARTY);
		Engine->StringHelper->Replace(partyPlayerName, xorstr(" "), xorstr("")); // Değişken güncellendi
		if (partyCount < 1)
			result << uint8(1) << partyPlayerName.c_str(); // Değişken güncellendi
		else
			result << uint8(3) << partyPlayerName.c_str() << uint8(0); // Değişken güncellendi

		Engine->Send(&result);

		__asm
		{
			mov ecx, esxx
			call setVisible

		}
		return;
	}
	else if (elementname == "btn_info")
	{
		DWORD tmp1 = 0;

		// UYARI GİDERİLDİ (C4189): Kullanılmayan 'isVisible' değişkeni silindi.

		Engine->GetChildByID(esxx, std::string("base_default"), tmp1);
		*(DWORD*)(tmp1 + 0x10D) = Engine->IsVisible(tmp1) ? false : true;
		Engine->GetChildByID(esxx, std::string("btn_view"), tmp1);


		*(DWORD*)(tmp1 + 0x10D) = Engine->IsVisible(tmp1) ? false : true;
		Engine->GetChildByID(esxx, std::string("btn_duel"), tmp1);

		*(DWORD*)(tmp1 + 0x10D) = Engine->IsVisible(tmp1) ? false : true;
		Engine->GetChildByID(esxx, std::string("btn_party"), tmp1);
		*(DWORD*)(tmp1 + 0x10D) = Engine->IsVisible(tmp1) ? false : true;
		Engine->GetChildByID(esxx, std::string("pus_gift"), tmp1);
		*(DWORD*)(tmp1 + 0x10D) = Engine->IsVisible(tmp1) ? false : true;

	}
}
__declspec(naked) void hkPMCloseWindowRecv()
{

	__asm {

		pushad
		pushfd
		mov ecx, ecx
		mov edx, ebx
		MOV pmBase, esi
		call setPMRecv
		popfd
		popad
		jmp KO_WHISPER_RECV_ORG

	}

}

__declspec(naked) void hkPMView()
{

	__asm {

		pushad
		pushfd
		mov ecx, esi
		call msgaa
		popfd
		popad
		jmp KO_WHISPER_VIEWMESAAGE_ORG

	}

}

/*Merchant Eye / HidePlayer*/
DWORD nPlayerRender = 0x005A6E9E;
DWORD nPlayerRenderOrg;
DWORD nPlayerRender1 = 0x005A7356;

bool _fastcall kendimmi(DWORD nPlayerBase)
{

	if (!Engine->m_bHookStart)return false;
	if (Engine->Player.ZoneID == 21)
	{
		if (Engine->m_UiMgr->uiMerchantEye != NULL && Engine->m_UiMgr->uiMerchantEye->IsVisible())
		{
			if (Engine->m_UiMgr->uiMerchantEye->search_merchant->GetString().empty())
				return false;

			uint16 sSocket = *(uint16*)(nPlayerBase + KO_OFF_ID);
			if (sSocket == Engine->GetSocketID())
				return false;
			if (sSocket > 8000)
				return false;
			Engine->MerchantEyeLockData.lock();
			if (Engine->MerchantID.size() == 0)
			{
				Engine->MerchantEyeLockData.unlock();
				return true;
			}
			auto itr = Engine->MerchantID.find(sSocket);
			if (itr == Engine->MerchantID.end())
			{
				*(uint8*)(nPlayerBase + KO_WH) = 0;
				*(uint8*)(nPlayerBase + 0x7AC) = 3;
				Engine->MerchantEyeLockData.unlock();
				return true;
			}
			Engine->MerchantEyeLockData.unlock();
			*(uint8*)(nPlayerBase + KO_WH) = 1;

			return false;
		}
		else if (Engine->m_UiMgr->uiMerchantEye != NULL && !Engine->m_UiMgr->uiMerchantEye->IsVisible())
		{
			uint16 sSocket = *(uint16*)(nPlayerBase + KO_OFF_ID);
			if (sSocket == Engine->GetSocketID())
				return false;
			if (sSocket > 8000)
				return false;
			uint8 sAuthority = *(uint8*)(nPlayerBase + KO_WH);
			if (sAuthority == 0)
				*(uint8*)(nPlayerBase + KO_WH) = 1;
		}
	}
	if (!isHideUser)return false;

	uint16 mSocket = *(uint16*)(nPlayerBase + KO_OFF_ID);
	if (mSocket > 8000)
		return false;

	if (mSocket == Engine->GetSocketID())
		return false;


	return true;
}
__declspec(naked) void hkPlayerRender()
{
	__asm
	{
		pushad
		pushfd
		mov ecx, esi
		call kendimmi
		movzx eax, al
		test eax, eax
		jne devam
		popfd
		popad

		jmp nPlayerRenderOrg
		devam :
		popfd
			popad
			jmp nPlayerRender1

	}
}


/*Merchant Eye / HidePlayer*/

/**/
const DWORD READ_MERCHANT_ADRESS = 0x0063939C;
DWORD READ_MERCHANT_ADRESS_ORG = 0;
__declspec(naked) void ReadNearMerchant()
{
	__asm
	{
		pushad
		pushfd
		mov sSocketMerchant, eax
		popfd
		popad

		jmp READ_MERCHANT_ADRESS_ORG

	}
}
const DWORD READ_MERCHANT_SPECIAL_ADRESS = 0x00639E18;
DWORD READ_MERCHANT_ADRESS_SPECIAL_ORG = 0;
__declspec(naked) void ReadNearMerchantSpecial()
{
	__asm
	{
		pushad
		pushfd
		mov sSocketMerchantSpecial, eax
		popfd
		popad

		jmp READ_MERCHANT_ADRESS_SPECIAL_ORG

	}
}
/**/
/*Merchant Price*/
/**//*Merchant Price*/
DWORD tooltipasm = 0x0086EF0B;
DWORD tooltipasm2 = 0x0086EF12;

// UYARI GİDERİLDİ (C4100): 'ebx' kullanılmadığı için yoruma alındı.
bool _fastcall ustundeyimamk(DWORD /*ebx*/)
{
	if (Engine->IsVisible(Engine->merchantdisplaydata))
	{
		if (sSocketMerchant > 10000 || sSocketMerchant < 1)
			return 0;

		uint8 getdata = 0;
		bool yoklama = false;
		for (int i = 0; i < 4; i++)
		{
			if (Engine->IsIn(Engine->merchantdisplayItem[i], Engine->lastMousePos.x, Engine->lastMousePos.y))
			{
				getdata = (uint8)i; // UYARI GİDERİLDİ
				yoklama = true;
				break;
			}
		}
		if (yoklama)
			return true;

	}
	else if (Engine->IsVisible(Engine->merchantdisplaySpecialdata))
	{
		if (sSocketMerchantSpecial > 10000 || sSocketMerchantSpecial < 1)
			return 0;

		uint8 getdata = 0;
		bool yoklama = false;
		for (int i = 0; i < 8; i++)
		{
			if (Engine->IsIn(Engine->merchantdisplaySpecialItem[i], Engine->lastMousePos.x, Engine->lastMousePos.y))
			{
				getdata = (uint8)i; // UYARI GİDERİLDİ
				yoklama = true;
				break;
			}
		}
		if (yoklama)
			return true;

	}
	return false;
}

__declspec(naked) void SetPriceMerchant()
{
	__asm
	{
		pushad
		pushfd
		cmp edx, 1
		je pricegoster
		mov ecx, ebx
		call ustundeyimamk
		movzx eax, al
		test eax, eax
		jne pricegoster
		popfd
		popad
		push 0
		jmp tooltipasm2
		pricegoster :
		popfd
			popad
			push 1
			jmp tooltipasm2
	}
}
const DWORD KO_GENIE_MOVE_JMP = 0x009C7563;						// Genie range of activities ayari buradan fixlendi.
DWORD KO_GENIE_MOVE_ORG;
__declspec(naked) void hkGenieMove()
{
	__asm
	{
		pushad
		pushfd

	}
	if (!__genieAttackMove)
	{
		__asm
		{
			popfd
			popad
			jmp KO_GENIE_MOVE_JMP

		}
	}
	__asm
	{
		popfd
		popad
		jmp KO_GENIE_MOVE_ORG
	}

}
DWORD KO_GENIE_MOVE_ORG2;
const DWORD KO_GENIE_MOVE_RETURN = 0x009C58DA;
__declspec(naked) void hkGenieMove2()
{
	__asm
	{
		pushad
		pushfd

	}
	if (!__genieAttackMove)
	{
		__asm
		{
			popfd
			popad
			MOV DWORD PTR DS : [0x009C7AE6] , 0x8638000090903CEB
			jmp KO_GENIE_MOVE_RETURN

		}
	}
	__asm
	{
		popfd
		popad
		MOV DWORD PTR DS : [0x009C7AE6] , 0x863800000107850F
		jmp KO_GENIE_MOVE_ORG2
	}

}
const DWORD KO_PARTY_REQUEST = 0x0052FED9;
DWORD KO_PARTY_REQUEST_KEEP = 0;
DWORD mLevel = 0;
DWORD tLevel = 0;
const DWORD KO_PARTY_REQUEST_JMP = 0x0052FF64;
void __declspec(naked) hkPartyRequest()
{
	__asm {
		pushad
		pushfd
		cmp ecx, 0xE1
		jb KO_PARTY_GO
		cmp ebx, 0xE1
		jae KO_PARTY_GO
		popfd
		popad
		jmp KO_PARTY_REQUEST_KEEP
		KO_PARTY_GO :
		popfd
			popad
			jmp KO_PARTY_REQUEST_JMP
	}
}
DWORD PearlEngine::GetTarget()
{
	// UYARI GİDERİLDİ: KO_ADR yerine loc_KO_ADR kullanıldı (C4459)
	DWORD loc_KO_ADR = *(DWORD*)KO_PTR_CHR;
	// UYARI GİDERİLDİ: uint16 cast eklendi (C4244)
	uint16 targetID = (uint16) * (DWORD*)(loc_KO_ADR + KO_OFF_MOB);
	if (targetID >= NPC_BAND)
	{
		Func_GetObjectBase = (tGetObjectBase)KO_FMBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, targetID, 1);
	}
	else {
		Func_GetObjectBase = (tGetObjectBase)KO_FPBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, targetID, 1);
	}
}
DWORD PearlEngine::GetTarget(uint16 targetID)
{
	// UYARI GİDERİLDİ (C4189): Kullanılmayan 'loc_KO_ADR' değişkeni tamamen silindi.
	uint16 byTargetID = targetID;
	if (byTargetID >= 10000)
	{
		Func_GetObjectBase = (tGetObjectBase)KO_FMBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, byTargetID, 1);
	}
	else {
		Func_GetObjectBase = (tGetObjectBase)KO_FPBS;
		return Func_GetObjectBase(*(DWORD*)KO_FLDB, byTargetID, 1);
	}
}
const DWORD KO_PREMIUM_STRING = 0x0082E807;
const DWORD KO_PREMIUM_STRING_CONTINUE = 0x0082E8A7;
const DWORD KO_PREMIUM_STRING_BACK = 0x0082E80D;
const DWORD KO_PREMIUM_STRING_CALL = 0x00A2FC20;

void __declspec(naked) hkPremiumString()
{
	__asm
	{
		movzx eax, byte ptr[esp + 0x17]
		cmp eax, 0x4
		je setPremium
		DEC EAX
		jmp KO_PREMIUM_STRING_BACK
		ret
		setPremium :
		lea edx, [esp + 0x00000F4]
			push edx
			push 0x5CA // 1482
			call KO_PREMIUM_STRING_CALL
			jmp KO_PREMIUM_STRING_CONTINUE
			ret
	}
}


/*28.04.2024 assist clan çizgisi*/
const DWORD hkPlayerBorderLine = 0x0058A0EF; // 2383
const DWORD BorderistOkey = 0x0058A0FA; // 2383
const DWORD Borderistnot = 0x0058A13F; // 2383
const DWORD BorderColor = 0x0058A11F; // 2383
const DWORD BorderColorback = 0x0058A124; // 2383
DWORD BorderColorORG;
DWORD KO_PLAYER_BORDER_LINE_ORG;
DWORD DWCOLOR;
bool _fastcall famecolor(DWORD fame)
{

	if (fame == 0x01 || fame == 0x02)
	{
		DWCOLOR = (fame == 0x01 ? 0xFF00FF00 : D3DCOLOR_ARGB(255, 255, 0, 228));
		return true;
	}
	return false;
}

__declspec(naked) void hkPlayerBorderColor()
{
	__asm {

		PUSH DWCOLOR
		jmp BorderColorback
	}
}

__declspec(naked) void hkPlayerBorder()
{
	__asm {
		__asm {
			pushad
			pushfd
			mov ecx, eax
			call famecolor
			popfd
			popad
			cmp eax, 1
			je 	pkBackgeri
			cmp eax, 2
			je 	pkBackgeri
			jmp Borderistnot
			pkBackgeri :
			push BorderistOkey
				ret
		}
	}
}
/*28.04.2024 assist clan çizgisi*/


//Clan cizgi Xtreme baslangic
const DWORD KO_FNC_TREE_CLAN_RENDER_RET = 0x583DF2; // 2383
const DWORD KO_FNC_TREE_CLAN_RENDER_USER = 0x583E39; // 2383
const DWORD KO_FNC_TREE_CLAN_RENDER_NEXT = 0x583DFD; // 2383
DWORD color_tree_rander = 0xff00ff00;
uint8_t __declspec(naked) Object_ClanTreeRanderHook()
{
	__asm
	{
		PUSH ESI
		MOV ESI, ECX
		CMP ESI, 1
		JE render_clan
		CMP ESI, 2
		JE render_clan
		XOR AL, AL
		POP ESI
		RETN
		render_clan :
		CMP ESI, 1
			MOV EAX, 0xFFFF00E4
			MOV ECX, 0xFF00FF00
			CMOVE EAX, ECX
			MOV DWORD PTR DS : color_tree_rander, EAX
			MOV AL, 1
			POP ESI
			RETN
	}
}
void __declspec(naked) hkClanTreeRanderHook()
{
	__asm
	{
		PUSHAD
		PUSHFD
		MOV ECX, EAX
		CALL Object_ClanTreeRanderHook
		POPFD
		POPAD
		CMP EAX, 1
		JE render_clan
		CMP EAX, 2
		JE render_clan
		JMP DWORD PTR DS : [KO_FNC_TREE_CLAN_RENDER_USER]
		render_clan :
		PUSH DWORD PTR DS : [KO_FNC_TREE_CLAN_RENDER_NEXT]
		RETN
	}
}


//Clan cizgi YNG verdigi kisim son

DWORD WINAPI PearlEngine::EngineMain(PearlEngine * e)
{
	Func_GetObjectBase = (tGetObjectBase)KO_FMBS;

	memcpy((void*)0x0052FED5, (char*)"\x90\x90", 2);
	DetourFunction((PBYTE)KO_PREMIUM_STRING, (PBYTE)hkPremiumString);
	//Clan cizgi sorunu fx xtreme 2383
	DetourFunction((PBYTE)KO_FNC_TREE_CLAN_RENDER_RET, (PBYTE)hkClanTreeRanderHook);
	KO_PARTY_REQUEST_KEEP = (DWORD)DetourFunction((PBYTE)KO_PARTY_REQUEST, (PBYTE)hkPartyRequest);
	CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)SendTarama, (LPVOID)KO_SND_FNC, NULL, NULL);
	DetourFunction((PBYTE)tooltipasm, (PBYTE)SetPriceMerchant);
	//KO_GENIE_MOVE_ORG = (DWORD)DetourFunction((PBYTE)0x009C7551, (PBYTE)hkGenieMove); // Atak Range Sifir oldugunda yürümesi engellendi.
	KO_GENIE_MOVE_ORG2 = (DWORD)DetourFunction((PBYTE)0x009C5769, (PBYTE)hkGenieMove2); // Basic Attack off Genie
	READ_MERCHANT_ADRESS_ORG = (DWORD)DetourFunction((PBYTE)READ_MERCHANT_ADRESS, (PBYTE)ReadNearMerchant);
	READ_MERCHANT_ADRESS_SPECIAL_ORG = (DWORD)DetourFunction((PBYTE)READ_MERCHANT_SPECIAL_ADRESS, (PBYTE)ReadNearMerchantSpecial);
	KO_ZONE_LOAD_TERRAIN_ORG = (DWORD)DetourFunction((PBYTE)KO_ZONE_LOAD_TERRAIN, (PBYTE)hkLoadTerrainData);
	DetourFunction((PBYTE)KO_AUTO_ATTACK, (PBYTE)hkAttack);
	//rtOrg = (DWORD)DetourFunction((PBYTE)KO_UIF_SET_FONT_STRING, (PBYTE)hkSetFontString);		// string kalinlastirma.
	TICK_ORG = (DWORD)DetourFunction((PBYTE)KO_GAME_TICK, (PBYTE)hkTick);
	KO_MAGIC_SKILL_ANIMATION_ORG = (DWORD)DetourFunction((PBYTE)0x009C3360, (PBYTE)GetAnimationSkill);
	(tUIOnKeyPress)DetourFunction((PBYTE)0x40F0F0, (PBYTE)hkUIOnKeyPress);
	*(float*)0xDFCBB8 = 1.0f / 999.0f;																	// -------------------- fps limiti kaldirma
	*(uint16*)0x007DA5F5 = 0x4FEB;																		// -------------------- klan parasi client kontrol kapatma
	nPlayerRenderOrg = (DWORD)DetourFunction((PBYTE)nPlayerRender, (PBYTE)hkPlayerRender);				// -------------------- PlayerRender Oyuncu Gizleme / Merchant Eye
	DetourFunction((PBYTE)kontrolAdresi, (PBYTE)hkRank);												// -------------------- Zindanwar Rank 
	DetourFunction((PBYTE)Func_RangeInstance, (PBYTE)hkRangeInstance);									// -------------------- mage alan kisitlama  
	DetourFunction((PBYTE)Func_AreaMove, (PBYTE)hkAreaMove);											// -------------------- mage alan kisitlama
	oShellExecuteA = (tShellExecuteA)DetourFunction((PBYTE)ShellExecuteA, (PBYTE)hkShellExecuteA);
	DetourFunction((PBYTE)KO_FNC_END_GAME, (PBYTE)hkEndGame);											// -------------------- Oyundan Hizli çikma
	memcpy((void*)0x0066B84C, (char*)"\xC7\x81\x24\x01\x00\x00\x00\x00\x00\x00", 10);					// Pazar bekleme süresi kapatma
	memcpy((void*)0x43384B, (char*)"\xE9\x34\x1\x0\x0\x90", 6);											// Inventory Animasyon patlamasi fix
	*(uint64*)0x0057305C = 0xDD9090000000E6E9;															// Oyuncularin bir anda geç yüklenmesinin düzeltildigi yer. Örnegin warriorun descenti veya town atma
	*(uint16*)0x00614C6A = 0x00003481;																	// Bdw'de ,Border'da Vip Key açilmama sorunu fixlendi.
	KO_WHISPER_GETMESSAGE_ORG = (DWORD)DetourFunction((PBYTE)0x0073372B, (PBYTE)hkPMMessage);
	KO_WHISPER_VIEWMESAAGE_ORG = (DWORD)DetourFunction((PBYTE)0x0072FCF3, (PBYTE)hkPMView);
	KO_WHISPER_OPEN_ORG = (DWORD)DetourFunction((PBYTE)0x0072FD33, (PBYTE)hkPMCloseWindow);
	KO_WHISPER_RECV_ORG = (DWORD)DetourFunction((PBYTE)0x00733840, (PBYTE)hkPMCloseWindowRecv);
	KO_WHISPER_CREATE_ORG = (DWORD)DetourFunction((PBYTE)0x00733090, (PBYTE)hkPMCreateWindow);
	*(uint32*)0x004F6AEF = 0x0000A6E9;																	// nick izin verme yeri Örn : ___ :: gibi degisik karakterlerde yazilabilir.
	*(uint8*)0x0052FEC3 = 0x5A;																			// 90 Level için Max Level diff kapatma
	//*(uint8*)0x009A8E67 = 0; //yanlis adres	    													// Geniede priest ölenin basina gitmesi fixlendi.
	*(uint16*)0x009C6BB3 = 0x4FEB;																		// Geniede priest ölenin basina gitmesi fixlendi.
	//*(uint16*)0x009C6BC9 = 0xEB39;*/																	// Geniede priest ölenin basina gitmesi fixlendi.
	*(uint16*)0x0067DA8D = 0x27EB;																		// Chaos bittikten sonra skillbar uifi çiftlenmesi fixlendi.
	ASMPatch((DWORD)0x0517411, (char*)"\xEB\x04\x90\x90\x90\x90\xD9\xEE", 8);	    					// Objeleri yakindan seri taramasi fix.



	/*24.09.2024 assist clan çizgisi Xtreme*/
	KO_PLAYER_BORDER_LINE_ORG = (DWORD)DetourFunction((PBYTE)hkPlayerBorderLine, (PBYTE)hkPlayerBorder);
	BorderColorORG = (DWORD)DetourFunction((PBYTE)BorderColor, (PBYTE)hkPlayerBorderColor);
	/*24.09.2024 assist clan çizgisi Xtreme */


	*(uint8*)(0x00679744) = 0xEB; //monster stone party check! xtreme 2383
	//#if (HOOK_SOURCE_VERSION == 1098)
#if 0
	// -------------------- hp progress animasyon iptali
	DWORD flt = (DWORD)malloc(sizeof(float));
	DWORD flt2 = (DWORD)malloc(sizeof(float));
	*(float*)flt = 0.0f;
	*(float*)flt2 = 1000.0f;
	// -------------------- hpbar
	*(DWORD*)(0x00842816 + 2) = flt;
	*(DWORD*)(0x00842848 + 2) = flt;
	*(DWORD*)(0x0084287E + 2) = flt;
	*(DWORD*)(0x008428B0 + 2) = flt;
	*(DWORD*)(0x008428E2 + 2) = flt;
	*(DWORD*)(0x00842863 + 2) = flt;
	*(DWORD*)(0x008425BE + 2) = flt;
	// -------------------- targetbar
	*(DWORD*)(0x0085BE22 + 2) = flt2;
	*(DWORD*)(0x0085BE2A + 2) = flt2;
	*(DWORD*)(0x0085BD11 + 2) = flt2;
	*(DWORD*)(0x0085BD19 + 2) = flt2;
	*(DWORD*)(0x0085BD91 + 2) = flt2;
	*(DWORD*)(0x0085BD89 + 2) = flt2;
#endif
	//// -------------------- slide görüntü bugu fix
	DWORD slidebug = (DWORD)malloc(sizeof(float));
	*(float*)slidebug = 0.75f;
	*(DWORD*)(0x514EC1 + 2) = slidebug;

	//// -------------------- direction görüntü bugu fix
	DWORD directionbug = (DWORD)malloc(sizeof(float));
	//*(float*)directionbug = 0.35f;
	*(float*)directionbug = 1.5f;
	*(DWORD*)(0x514FDB + 2) = directionbug;


	// -------------------- Discord yükleme
	e->dc = new Discord;
	/*if (e->dc = new Discord) {
		e->dc->Initialize();
		e->dc->Update();
	}*/

	// -------------------- Anti afk ve kafaya yazi yazma
	DetourFunction((PBYTE)KO_FNC_OBJECT_MOB_LOOP, (PBYTE)hkObjectMobLoop);
	KO_FNC_OBJECT_PLAYER_LOOP_ORG = (DWORD)DetourFunction((PBYTE)KO_FNC_OBJECT_PLAYER_LOOP, (PBYTE)hkObjectPlayerLoop);

	DetourFunction((PBYTE)fncScanZ, (PBYTE)hkZ);
	DetourFunction((PBYTE)fncScanB, (PBYTE)hkB);
	DetourFunction((PBYTE)KO_FNC_GENIE_SCAN, (PBYTE)hkGenieSelect);

	oGetChild = (tGetChild)DetourFunction((PBYTE)KO_GET_CHILD_BY_ID_FUNC, (PBYTE)GetChildByID_Hook);
	oSetVisible = (htSetVisible)DetourFunction((PBYTE)0x00411980, (PBYTE)SetVisible_Hook);
	oSetUIPos = (tSetUIPos)DetourFunction((PBYTE)0x0040F7D0, (PBYTE)SetUI_Hook);

	// -------------------- death animasyon speed 
	DWORD deathTimeAdress = 0x0054191E;
	DWORD newSleep = (DWORD)malloc(sizeof(float));

	// UYARI GİDERİLDİ (C6011): newSleep'in boş olma (NULL) ihtimaline karşı kontrol eklendi.
	if (newSleep != 0)
	{
		*(float*)newSleep = 0.0f;
		*(DWORD*)(deathTimeAdress + 2) = newSleep;
	}

	// --------------------	Login intro kapatma
	// --------------------	Login intro kapatma
	{
		uint8 wValues[] = { 0x8B, 0x0D, 0xF4, 0x0F, 0xF5, 0x00 };
		for (auto i = 0; i < sizeof(wValues) / sizeof(wValues[0]); i++)
			*(BYTE*)(0x00A9C009 + i) = wValues[i];
	}
	// --------------------
	*(DWORD*)0xC88ACC = (DWORD)hkDisableVisible;								// -------------------- scheculer Gizleme
	*(DWORD*)0xC87924 = (DWORD)hkDisableVisible;								// -------------------- day price Gizleme
	*(DWORD*)0xC8DA0C = (DWORD)hkDisableVisible;								// -------------------- CUIItemtimeBtn Gizleme
	//DetourFunction((PBYTE)0x7E4670, (PBYTE)hkDisableVisible);						// -------------------- Quest View Ekrani Gizleme
	memcpy((void*)0x0091006D, (char*)"\x90\x90\x90\x90\x90\x90", 6);			// -------------------- TempItem Item List 1 Gizleme
	*(DWORD*)0xC8D91C = (DWORD)hkDisableVisible;								// -------------------- TempItem Item List 2 Gizleme
	DetourFunction((PBYTE)KO_SKILLBAR_MOUSE_INPUT, (PBYTE)hkSkillbarMouseInput);		// geniemacro
	DetourFunction((PBYTE)KO_SKILLBAR_SHORTCUT_INPUT, (PBYTE)hkSkillbarShortcutInput);	// geniemacro
	KO_SKILLBAR_KEY_INPUT_KEEP = (DWORD)DetourFunction((PBYTE)KO_SKILLBAR_KEY_INPUT, (PBYTE)hkSkillbarKeyInput);

#if (HOOK_SOURCE_VERSION == 1098)
	DetourFunction((PBYTE)GetMark, (PBYTE)hkMarkPos);									// --------------------	Civciv iconu Çalistiran fonksiyon
	*(DWORD*)0x00575B10 = 0x90C3C031;											// -------------------- Karakter Space animasyonu iptal etme
	*(DWORD*)0x00575B10 = 0x90C3C031;											// -------------------- Karakter Space animasyonu iptal 
	*(DWORD*)0xC7FF24 = (DWORD)hkDisableVisible;								// -------------------- timeleft Gizleme
	//*(DWORD*)0xC82ABC = (DWORD)hkOpenMiniMapfromGlobal;						// -------------------- globalmap to minimap
	*(DWORD*)0xC8A914 = (DWORD)hkDisableVisible;								// -------------------- H command achieve Gizleme
	*(DWORD*)0xC8430C = (DWORD)hkDisableVisible;								// -------------------- QuestSeed  Gizleme
	*(DWORD*)0xC7D684 = (DWORD)hkDisableVisible;								// -------------------- Nation Channel List Gizleme
	memcpy((void*)0x00797746, (char*)"\xEB\x14", 2);							// -------------------- Training  Gizleme
	memcpy((void*)0x008EE8B0, (char*)"\x31\xC0\xC2\x4\x0", 5);					// -------------------- Commander Skill Bar Gizleme
	//memcpy((void*)0x0081A920, (char*)"\C3\x90\x90", 3);						// -------------------- Minimap Gizleme  -- Çalistirinca f10 seed helper game option 2 patliyor.
	memcpy((void*)0x005A212A, (char*)"\xE9\xBB\x01\x00\x00\x90", 6);			// -------------------- Noah knight Pelerin Kapatma & Gizleme

	// -------------------- minimap sabitleme
	memcpy((void*)0x00841FB2, (char*)"\x90\x90", 2);
	memcpy((void*)0x0085659F, (char*)"\x90\x90", 2);
	(DWORD)DetourFunction((PBYTE)0x00841FFA, (PBYTE)hkMinimapPos);
	// --------------------

	// -------------------- noah knight level degistirme
	uint8 noah_max_level = 30;
	*(BYTE*)0x558119 = noah_max_level - 1;
	*(BYTE*)0x55822B = noah_max_level;
	*(BYTE*)0x00558384 = noah_max_level - 1;
	*(BYTE*)0x005583AA = noah_max_level;
	*(BYTE*)0x00553AAB = noah_max_level - 1;
	*(BYTE*)0x00547934 = noah_max_level - 1;
	// ----------------- 


	// ----------------- v1098 Character Select Uif Animasyonu ve set pos'un iptali 
	{
		uint8 wValues[6] = { 0xE9, 0x0E, 0x01, 0x00, 0x00, 0x90 };
		for (auto i = 0; i < sizeof(wValues) / sizeof(wValues[0]); i++)
			*(DWORD*)(0x004F766F + i) = wValues[i];
	}

	{
		uint8 wValues[6] = { 0xE9, 0x0B, 0x01, 0x00, 0x00, 0x90 };
		for (auto i = 0; i < sizeof(wValues) / sizeof(wValues[0]); i++)
			*(DWORD*)(0x004F788D + i) = wValues[i];
	}
	// ----------------- 


	// -------------------- 1098 genie set pos
	//KO_SET_UI_ORG = (DWORD)DetourFunction((PBYTE)0x0040F7D0, (PBYTE)hkUiPos);
	*(DWORD*)0xC86900 = (DWORD)hkGenieSetPos;
	KO_SET_EVENTNOTICE_POS_ORG = (DWORD)DetourFunction((PBYTE)KO_SET_EVENTNOTICE_POS, (PBYTE)hkEventNotice);
	/*uint8 channelY = 63;  //nxwile military camp görünmüyordu fix
	*(char*)0x0055B6D5 = channelY;
	*(char*)0x0050335C = channelY;
	*(char*)0x0050335B = 0x6A;*/
	// --------------------

	/* Tahtli Karakter Kordinatlari */
	Real_CharacterSelectLeft_ORG = (DWORD)DetourFunction((PBYTE)Real_CharacterSelectLeft, (PBYTE)Hook_CharacterSelectLeft);			// -------------------- Tahtli karakter
	Real_CharacterSelectRight_ORG = (DWORD)DetourFunction((PBYTE)Real_CharacterSelectRight, (PBYTE)Hook_CharacterSelectRight);		// -------------------- Tahtli karakter

	*(DWORD*)(0x004EB5F9) = 0;
	{	// 1
		static float fX = -0.01f;
		static float fY = -1.16f;
		static float fZ = 2.6f;
		static float fR = 0.0f;

		*(DWORD*)(0x004EE0B8 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EE0AE + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EE099 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EE0C3 + 2) = (DWORD)(&fR);
	}
	{	// 2
		static float fX = 1.73f;
		static float fY = -1.16f;
		static float fZ = 2.0f;
		static float fR = 0.68539819;

		*(DWORD*)(0x004EE051 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EE047 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EE032 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EE05C + 2) = (DWORD)(&fR);
	}
	{	// 3
		static float fX = -1.82f;
		static float fY = -1.16f;
		static float fZ = 1.95f;
		static float fR = -0.68539819;

		*(DWORD*)(0x004EE11B + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EE111 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EE0FC + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EE126 + 2) = (DWORD)(&fR);
	}
	{	// C1
		static float fX = 0.0f;
		static float fY = -1.16f;
		static float fZ = 3.8f;
		static float fR = 0.78539819;

		*(DWORD*)(0x004EAB25 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EAB39 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EAB46 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EA9C6 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EA9DB + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EA9E9 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EAA16 + 2) = (DWORD)(&fR);
	}
	{	// C2
		static float fX = 2.60f;
		static float fY = -1.16f;
		static float fZ = 2.9f;
		static float fR = 1.28539819;

		*(DWORD*)(0x004EAB5D + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EAB71 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EAB7E + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EAA30 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EAA3E + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EAA48 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EAA6C + 2) = (DWORD)(&fR);
	}
	{	// C3
		static float fX = -2.7f;
		static float fY = -1.16f;
		static float fZ = 2.9f;
		static float fR = -0.18539819;

		*(DWORD*)(0x004EAB95 + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EABA9 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EABB6 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EAA8F + 2) = (DWORD)(&fX);
		*(DWORD*)(0x004EAAA3 + 2) = (DWORD)(&fY);
		*(DWORD*)(0x004EAAB0 + 2) = (DWORD)(&fZ);
		*(DWORD*)(0x004EAAD7 + 2) = (DWORD)(&fR);
	}
	// ----------------- 
	/* Tahtli Karakter Kordinatlari */

#elif (HOOK_SOURCE_VERSION == 1534)
	DetourFunction((PBYTE)GetMark, (PBYTE)hkMarkPos);									// --------------------	Civciv iconu Çalistiran fonksiyon
	*(DWORD*)0x00575B10 = 0x90C3C031;											// -------------------- Karakter Space animasyonu iptal etme
	*(DWORD*)0x00575B10 = 0x90C3C031;											// -------------------- Karakter Space animasyonu iptal 
	*(DWORD*)0xC8A914 = (DWORD)hkDisableVisible;								// -------------------- H command achieve Gizleme
	*(DWORD*)0xC8430C = (DWORD)hkDisableVisible;								// -------------------- QuestSeed  Gizleme
	*(DWORD*)0xC7D684 = (DWORD)hkDisableVisible;								// -------------------- Nation Channel List Gizleme
	memcpy((void*)0x00797746, (char*)"\xEB\x14", 2);							// -------------------- Training  Gizleme
	memcpy((void*)0x008EE8B0, (char*)"\x31\xC0\xC2\x4\x0", 5);					// -------------------- Commander Skill Bar Gizleme
	memcpy((void*)0x005A212A, (char*)"\xE9\xBB\x01\x00\x00\x90", 6);			// -------------------- Noah knight Pelerin Kapatma & Gizleme

	// -------------------- noah knight level degistirme
	uint8 noah_max_level = 30;
	*(BYTE*)0x558119 = noah_max_level - 1;
	*(BYTE*)0x55822B = noah_max_level;
	*(BYTE*)0x00558384 = noah_max_level - 1;
	*(BYTE*)0x005583AA = noah_max_level;
	*(BYTE*)0x00553AAB = noah_max_level - 1;
	*(BYTE*)0x00547934 = noah_max_level - 1;
	// ----------------- 


	// ----------------- v1098 Character Select Uif Animasyonu ve set pos'un iptali 
	{
		uint8 wValues[6] = { 0xE9, 0x0E, 0x01, 0x00, 0x00, 0x90 };
		for (auto i = 0; i < sizeof(wValues) / sizeof(wValues[0]); i++)
			*(DWORD*)(0x004F766F + i) = wValues[i];
	}

	{
		uint8 wValues[6] = { 0xE9, 0x0B, 0x01, 0x00, 0x00, 0x90 };
		for (auto i = 0; i < sizeof(wValues) / sizeof(wValues[0]); i++)
			*(DWORD*)(0x004F788D + i) = wValues[i];
	}
	// ----------------- 

	// -------------------- 1534 genie set pos
	//KO_SET_UI_ORG = (DWORD)DetourFunction((PBYTE)0x0040F7D0, (PBYTE)hkUiPos);
	*(DWORD*)0xC86900 = (DWORD)hkGenieSetPos;
	KO_SET_EVENTNOTICE_POS_ORG = (DWORD)DetourFunction((PBYTE)KO_SET_EVENTNOTICE_POS, (PBYTE)hkEventNotice);
	uint8 channelY = 63;
	*(char*)0x005686D5 = channelY;
	*(char*)0x00510E1C = channelY;
	*(char*)0x00510E1B = 0x6A;
	// --------------------
#else
	//* (DWORD*)0xC86900 = (DWORD)hkGenieSetPos; // genie set pos
	KO_SET_EVENTNOTICE_POS_ORG = (DWORD)DetourFunction((PBYTE)KO_SET_EVENTNOTICE_POS, (PBYTE)hkEventNotice);
#endif

#if ANTICHEAT_MODE == 0
	e->ScanThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)DriverScan, NULL, NULL, NULL);
	e->SuspendThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)SuspendCheck, e, NULL, NULL);
	e->TitleThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)TitleCheck, e, NULL, NULL);
	ProtectionMain();//Xtreme Dump 
	Dll_Inject();//Xtreme inject koruma 
	//memory_scan();//Xtreme Memory koruma 
#endif
#if XTREME_LISANS == 1
	e->LisansThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)LicenseEngine, e, NULL, NULL);
#endif
	e->AliveThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)AliveSend, NULL, NULL, NULL);
	e->AutoUpThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)AutoUpSend, NULL, NULL, NULL);
	e->Timerrr = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)TimersV2, e, NULL, NULL);

	// UYARI GİDERİLDİ: GetTickCount64 kullanıldı.
	e->m_bCheckSleep = GetTickCount64();
	e->m_LoginPlugInjected = true;

	while (true)
	{
		e->Update();
#if ANTICHEAT_MODE == 0
		if (IsDebuggerPresent())
			e->Shutdown(xorstr("Debugger"));

		if (e->IsHWBreakpointExists())
			e->Shutdown(xorstr("BreakPoint"));

		if (e->IsitaSandBox())
			e->Shutdown(xorstr("Sandbox"));
#endif
		if (WaitForSingleObject(e->ScanThread, 1) == WAIT_OBJECT_0
			|| WaitForSingleObject(e->SuspendThread, 1) == WAIT_OBJECT_0
			|| WaitForSingleObject(e->LisansThread, 1) == WAIT_OBJECT_0
			|| WaitForSingleObject(e->ClassThread, 1) == WAIT_OBJECT_0)
			Engine->Shutdown(xorstr("All the pieces of the game can't work together."));

		if (e->uiNoticeWind && getMSTime() > e->m_recentdelete_time)
		{
			e->uiNoticeWind->Clear();
			e->m_recentdelete_time = getMSTime() + (30 * 1000) * 60;
		}

		Sleep(100);
	}
	return TRUE;
}

void PearlEngine::Update()
{
	if (!m_bSelectedCharacter)
	{
		return;
	}

	if (!m_bGameStart)
	{
		return;
	}

	if (!isAlive)
		return;

	if (thisProc == NULL)
		thisProc = GetCurrentProcess();

	if (KO_ADR == 0x0)
		KO_ADR = *(DWORD*)KO_PTR_CHR;

	uint8 Authority;
	Authority = *(uint8*)(KO_ADR + KO_WH);
	if (this->Player.Authority != Authority)
	{
		if (Authority == USER || Authority == GAMEMASTER || Authority == BANNED)
		{
			tmpGraphics = "";
			for (string gpu : Player.GPU)
				tmpGraphics += xorstr(" | ") + gpu;

			this->Player.Authority = (UserAuthority)Authority;

			Packet result(XSafe);
			result << uint8_t(XSafeOpCodes::AUTHINFO) << Authority << tmpGraphics << Player.CPU;
			this->Send(&result);
#if ANTICHEAT_MODE == 1
			if (Authority != 0 && Authority != 1 && Authority != 2 && Authority != 11 && Authority != 12 && Authority != 250 && Authority != 255)
			{
				Shutdown(xorstr("Game closed due to memory editing\n"));
			}
#endif
		}
	}

	if (m_PlayerBase == NULL)
		m_PlayerBase = new CPlayerBase();

	if (m_PlayerBase != NULL)
		m_PlayerBase->UpdateFromMemory();
}

DWORD Read4Bytes(DWORD paddy)
{
	return *(int*)paddy;
}

void __stdcall LM_Shutdown(std::string log, std::string graphicCards, std::string processor)
{
	if (isAlive && gameStarted)
	{
		Packet result(XSafe);
		result << uint8_t(XSafeOpCodes::LOG) << log << graphicCards << processor;
		LM_Send(&result);
	}
	Shutdown(log);
}
const DWORD adrexxs = 0x0041FF40;

// UYARI GİDERİLDİ (C4100): 'uif' ve 'szFN' asm içinde kullanıldığı için yoruma alındı.
void __declspec(naked) SetTex(DWORD /*uif*/, const std::string& /*szFN*/)
{
	__asm {
		push ebp
		mov ebp, esp
		push[ebp + 0xC]
		mov ecx, [ebp + 8]
		call adrexxs
		pop ebp
		ret
	}
}

void PearlEngine::SetTexImage(DWORD uif, const std::string & szFN)
{
	if (szFN.empty()) { printf("%d \n", uif); return; }
	SetTex(uif, szFN);
}
void PearlEngine::Shutdown(std::string log)
{
	tmpGraphics = "";
	for (string gpu : Player.GPU)
		tmpGraphics += xorstr(" | ") + gpu;
	LM_Shutdown(log, tmpGraphics, Player.CPU);
}

void LM_Send(Packet * pkt)
{
	if (isAlive)
	{
		uint8 opcode = pkt->GetOpcode();
		uint8* out_stream = nullptr;
		uint16 len = (uint16)(pkt->size() + 1);

		out_stream = new uint8[len];
		out_stream[0] = pkt->GetOpcode();

		if (pkt->size() > 0)
			memcpy(&out_stream[1], pkt->contents(), pkt->size());

		BYTE* ptrPacket = out_stream;
		SIZE_T tsize = len;

		__asm
		{
			mov ecx, KO_PTR_PKT
			mov ecx, DWORD ptr ds : [ecx]
			push tsize
			push ptrPacket
			call KO_SND_FNC
		}

		delete[] out_stream;
	}
}

bool dirExists(const std::string & dirName_in)
{
	DWORD ftyp = GetFileAttributesA(dirName_in.c_str());
	if (ftyp == INVALID_FILE_ATTRIBUTES)
		return false;

	if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
		return true;

	return false;
}

std::string getHWID()
{
	HW_PROFILE_INFO hwProfileInfo;
	GetCurrentHwProfile(&hwProfileInfo);
	string hwidWString = hwProfileInfo.szHwProfileGuid;
	string hwid(hwidWString.begin(), hwidWString.end());
	return hwid;
}

void GetMacHash(uint16 & MACOffset1, uint16 & MACOffset2);
uint16 GetCPUHash();

uint16 GetVolumeHash()
{
	DWORD SerialNum = 0;
	GetVolumeInformationA(xorstr("C:\\"), NULL, 0, &SerialNum, NULL, NULL, NULL, 0);
	uint16 nHash = (uint16)((SerialNum + (SerialNum >> 16)) & 0xFFFF);
	return nHash;
}

int64 GetHardwareID()
{
	uint16 MACData1, MACData2 = 0;
	GetMacHash(MACData1, MACData2);
	return _atoi64(string_format(xorstr("%d%d%d"), MACData1, MACData2, GetCPUHash()).c_str());/*, GetVolumeHash()).c_str());*/ //09.10.2020 GetVolumaHash Kapatildi
	//Deger Uzun gelirse sikinti yaratabilirdi oyuncu oyuna giremeyebilirdi o sebeple kapatildi
}

uint16 HashMacAddress(PIP_ADAPTER_INFO info)
{
	uint16 nHash = 0;
	for (uint32 i = 0; i < info->AddressLength; i++)
		nHash += (info->Address[i] << ((i & 1) * 8));
	return nHash;
}
void GetMacHash(uint16 & MACOffset1, uint16 & MACOffset2)
{
	// Belleği Stack yerine Heap'ten (new ile) ayırıyoruz.
	// Artık 20KB stack işgal etmeyecek.
	IP_ADAPTER_INFO* AdapterInfo = new (std::nothrow) IP_ADAPTER_INFO[32];

	if (AdapterInfo == nullptr) return; // Bellek ayrılamadıysa çık

	DWORD dwBufLen = sizeof(IP_ADAPTER_INFO) * 32;

	DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen);
	if (dwStatus == ERROR_SUCCESS)
	{
		PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
		MACOffset1 = HashMacAddress(pAdapterInfo);

		if (pAdapterInfo->Next)
			MACOffset2 = HashMacAddress(pAdapterInfo->Next);

		if (MACOffset1 > MACOffset2)
		{
			uint16 TempOffset = MACOffset2;
			MACOffset2 = MACOffset1;
			MACOffset1 = TempOffset;
		}
	}

	// ÖNEMLİ: Heap'ten ayrılan belleği işimiz bitince siliyoruz.
	delete[] AdapterInfo;
}

uint16 GetCPUHash()
{
	int CPUInfo[4] = { 0, 0, 0, 0 };
	__cpuid(CPUInfo, 0);
	uint16 nHash = 0;
	uint16* nPointer = (uint16*)(&CPUInfo[0]);
	for (uint16 i = 0; i < 8; i++)
		nHash += nPointer[i];

	return nHash;
}



void StartHook()
{

	if (Engine->m_bHookStart) return;
	Engine->m_bHookStart = true;

	//DWORD genieadresi = 0x009C7D20; //  2369

	//DWORD genieNewCD = (DWORD)malloc(sizeof(float));
	//ASMPatch(genieadresi, (char*)"\xD8\x05", 2);
	//*(float*)genieNewCD = 0.3f;

	//*(DWORD*)(genieadresi + 2) = genieNewCD;

	Engine->InitCameraZoom();
	Engine->m_SettingsMgr = new CSettingsManager();
	Engine->m_SettingsMgr->Init();
	Engine->m_PlayerBase = new CPlayerBase();
	if (Engine->m_PlayerBase->isWarrior())
		isRFastAttack = true;
	//else if (Engine->m_PlayerBase->isRogue())
	//	genieNewCD = 1.6f;
	//else if (Engine->m_PlayerBase->isMage())
	//	genieNewCD = 1.6f;
	else if (Engine->m_PlayerBase->isPriest())
		isRFastAttack = true;

	Engine->varius = Engine->rdword(KO_DLG, std::vector<int>{ 0x208});

#if (HOOK_SOURCE_VERSION == 1098)
	//Plugins
	Engine->hkRightClickExchange = new RightClickExchange();
	Engine->uiState = new CUIStatePlug();
	Engine->uiTargetBar = new CUITargetBarPlug();
	Engine->uiTaskbarMain = new CUITaskbarMainPlug();
	Engine->uiTaskbarSub = new CUITaskbarSubPlug();
	Engine->uiClanWindowPlug = new CUIClanWindowPlug();
	Engine->uiPlayerRank = new HookPlayerRank();
	Engine->uiGenieSubPlug = new CUIGenieSubPlug();
	Engine->uiSeedHelperPlug = new CUISeedHelperPlug();
	Engine->uiTradePrice = new CUITradePricePlug();
	Engine->uiTradeInventory = new CUITradeInventoryPlug();
	Engine->uiTradeItemDisplay = new CUITradeItemDiplayPlug();
	Engine->uiTradeItemDisplaySpecial = new CUITradeItemDisplaySpecialPlug();
	Engine->m_MerchantMgr = new CMerchantManager();
	Engine->uiInventoryPlug = new CUIInventoryPlug();
	Engine->uiScoreBoard = new CUIScoreBoardPlug();
	Engine->uiGenieMain = new CUIGenieMain;
	Engine->uiHPBarPlug = new CUIHPBarPlug();
	Engine->uiHpMenuPlug = new CUIHPBarMenuPlug();
	Engine->uiTopRightNewPlug = new CUITopRightNewPlug();
	Engine->uiMinimapPlug = new CUIMinimapPlug;
	Engine->uiCindirella = new CUICindirellaPlug();
	Engine->uiCollection = new CUICollectionRacePlug();
	Engine->uiNoticeWind = new CUIMoticeMsgWnd();
	Engine->uiWheel = new CUIWheelOfFun();
	Engine->uiSearchMonster = new CUISearchMonsterDropPlug();
	Engine->uiDropResult = new CDropResult();
	Engine->uiTagChange = new CTagChange();
	Engine->uiSkillPage = new HookSkillPage();
	Engine->uiQuestComplated = new CUIQuestComplated();
	Engine->uiLottery = new CUILotteryEventPlug();
	Engine->uiEventShowList = new CEventShowListPlug();
	Engine->uiMerchantList = new CUIMerchantListPlug();
	Engine->uiInformationWind = new CUIInformationWindPlug();
	Engine->uiChatBarPlug = new CUIChatBarPlug();
	Engine->uiQuestPage = new HookQuestPage();
	Engine->uiSealToolTip = new CSealToolTip();
	Engine->uiPowerUpStore = new CUIPowerUpStore();
	Engine->uiPartyBBS = new CUIPartyBBSPlug();
	Engine->uiAccountRegisterPlug = new CUIAccountRegister();
	Engine->uiPieceChangePlug = new CUIPieceChangePlug();
	Engine->uiSupport = new CUISupportReportPlug();
	//Engine->uiEventNotice = new CUIEventNoticePlug(); //kullanilmiyor
	Engine->uiAnvil = new CUIAnvil();
	//Engine->uiToolTip = new CUITooltip(); //kullanilmiyor	
	//Engine->uiSchedularPlug = new CUISchedular;
	//Engine->uiMiniMenuPlug = new CUIMiniMenuPlug();
#else
	Engine->uiAnvil = new CUIAnvil();
	Engine->uiAccountRegisterPlug = new CUIAccountRegister();
	Engine->uiQuestComplated = new CUIQuestComplated();
	Engine->hkRightClickExchange = new RightClickExchange();
	Engine->uiState = new CUIStatePlug();
	Engine->uiTopRightNewPlug = new CUITopRightNewPlug();
	Engine->uiMinimapPlug = new CUIMinimapPlug;
	Engine->uiDropResult = new CDropResult();
	Engine->uiInformationWind = new CUIInformationWindPlug();
	Engine->uiNoticeWind = new CUIMoticeMsgWnd();
	Engine->uiGenieMain = new CUIGenieMain;
	Engine->uiGenieSubPlug = new CUIGenieSubPlug();
	Engine->uiEventShowList = new CEventShowListPlug();
	Engine->uiTargetBar = new CUITargetBarPlug();
	Engine->uiTaskbarMain = new CUITaskbarMainPlug();
	Engine->uiTaskbarSub = new CUITaskbarSubPlug();
	Engine->uiQuestPage = new HookQuestPage();
	Engine->uiClanWindowPlug = new CUIClanWindowPlug();
	Engine->uiMerchantList = new CUIMerchantListPlug();
	Engine->uiTradeInventory = new CUITradeInventoryPlug();
	Engine->uiTradeItemDisplay = new CUITradeItemDiplayPlug();
	Engine->uiTradeItemDisplaySpecial = new CUITradeItemDisplaySpecialPlug();
	Engine->m_MerchantMgr = new CMerchantManager();
	Engine->uiTradePrice = new CUITradePricePlug();
	Engine->uiPlayerRank = new HookPlayerRank();
	Engine->uiInventoryPlug = new CUIInventoryPlug();
	Engine->uiSeedHelperPlug = new CUISeedHelperPlug();
	Engine->uiHPBarPlug = new CUIHPBarPlug();
	Engine->uiScoreBoard = new CUIScoreBoardPlug();
	Engine->uiTagChange = new CTagChange();
	Engine->uiSkillPage = new HookSkillPage();
	Engine->uiSearchMonster = new CUISearchMonsterDropPlug();
	Engine->uiCindirella = new CUICindirellaPlug();
	Engine->uiPowerUpStore = new CUIPowerUpStore();
	Engine->uiCollection = new CUICollectionRacePlug();
	Engine->uiLottery = new CUILotteryEventPlug();
	Engine->uiHpMenuPlug = new CUIHPBarMenuPlug();
	Engine->uiSealToolTip = new CSealToolTip();
	Engine->uiWheel = new CUIWheelOfFun();
	Engine->uiPieceChangePlug = new CUIPieceChangePlug();
	Engine->uiSupport = new CUISupportReportPlug();
	Engine->uiMiniMenuPlug = new CUIMiniMenuPlug();
#endif

	Engine->m_bHookStart = true;
	Engine->m_UiMgr->OpenMerchantNotice();
#if (HOOK_SOURCE_VERSION == 1098)
	//uint8 Nation = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_OFF_NATION);
	//if (Nation == 1)
	//{
	//	POINT koScreen = *(POINT*)0x00DFC99C;
	//	RECT region = Engine->GetUiRegion(Engine->uiChatBarPlug->m_dVTableAddr);  // chatting Box ve information Box'in pozisyonun konumlandirildigi yer
	//	POINT orta;
	//	Engine->lastkoScreen = koScreen;
	//	Engine->curlastkoScreen = koScreen;
	//	LONG w = (region.right - region.left);
	//	orta.x = (koScreen.x / 2) - 513;
	//	orta.y = region.top + 1;
	//	Engine->SetUIPos(Engine->uiChatBarPlug->m_dVTableAddr, orta);
	//	orta.x = (koScreen.x / 2) + 214;
	//	Engine->SetUIPos(Engine->uiInformationWind->m_dVTableAddr, orta);
	//}
	//if (Nation == 2)
	//{
	//	POINT koScreen = *(POINT*)0x00DFC99C;
	//	RECT region = Engine->GetUiRegion(Engine->uiChatBarPlug->m_dVTableAddr);  // chatting Box ve information Box'in pozisyonun konumlandirildigi yer
	//	POINT orta;
	//	Engine->lastkoScreen = koScreen;
	//	Engine->curlastkoScreen = koScreen;
	//	LONG w = (region.right - region.left);
	//	orta.x = (koScreen.x / 2) - 513;
	//	orta.y = region.top - 12;
	//	Engine->SetUIPos(Engine->uiChatBarPlug->m_dVTableAddr, orta);
	//	orta.x = (koScreen.x / 2) + 215;
	//	Engine->SetUIPos(Engine->uiInformationWind->m_dVTableAddr, orta);
	//}
#endif
	//Engine->uiCollection->OpenCR();
	//Engine->uiCollection->SetVisible(false);

	if (true)
	{
		vector<int>offsets;
		offsets.push_back(0x2C8);
		offsets.push_back(0);

		Engine->merchantdisplaydata = Engine->rdword(KO_DLG, offsets);
		for (int i = 0; i < 4; i++)
		{
			std::string find = string_format("%d", i);
			Engine->GetChildByID(Engine->merchantdisplaydata, find, Engine->merchantdisplayItem[i]);
		}
	}
	if (true)
	{
		vector<int>offsets;
		offsets.push_back(0x2CC);
		offsets.push_back(0);

		Engine->merchantdisplaySpecialdata = Engine->rdword(KO_DLG, offsets);
		for (int i = 0; i < 8; i++)
		{
			std::string find = string_format("%d", i);
			Engine->GetChildByID(Engine->merchantdisplaySpecialdata, find, Engine->merchantdisplaySpecialItem[i]);
		}
	}
}

enum CollectionRaceType
{
	CRStartRecv,
	CRGetActiveTime,
	CRMonsterKilled,
	CRUpdateCounter,
	CRFinishRecv,
	CRHide
};

void CollectionRaceStart(Packet & pkt);
void CollectionRaceGetActiveTime(Packet & pkt);
void CollectionRaceHide();
void CollectionRaceDead(Packet & pkt);
void CollectionRaceUpdateCounter(Packet & pkt);
void CollectionRaceFinish();

void HandleCollectionRace(Packet & pkt)
{
	uint8 OpCode;
	pkt >> OpCode;

	switch (OpCode)
	{
	case CollectionRaceType::CRStartRecv:
		CollectionRaceStart(pkt);
		break;
	case CollectionRaceType::CRGetActiveTime:
		CollectionRaceGetActiveTime(pkt);
		break;
	case CollectionRaceType::CRMonsterKilled:
		CollectionRaceDead(pkt);
		break;
	case CollectionRaceType::CRUpdateCounter:
		CollectionRaceUpdateCounter(pkt);
		break;
	case CollectionRaceType::CRFinishRecv:
		CollectionRaceFinish();
		break;
	case CollectionRaceType::CRHide:
		CollectionRaceHide();
		break;
	default:
		break;
	}
}

void CollectionRaceStart(Packet& pkt)
{
	//Engine->uiCollection = NULL;	
	Engine->CrRandomReward = 0;// 10 lu yapim 17.05.2024 end
	pkt.DByte();
	Engine->IsCRActive = true;
	for (int i = 0; i < 3; i++)
	{
		pkt >> Engine->pCollectionRaceEvent.sSid[i] >> Engine->pCollectionRaceEvent.killTarget[i];
		Engine->pCollectionRaceEvent.killCount[i] = 0;
	}

	for (int i = 0; i < 10; i++)
	{
		pkt >> Engine->pCollectionRaceEvent.RewardsItemID[i] >> Engine->pCollectionRaceEvent.RewardsItemCount[i] >> Engine->pCollectionRaceEvent.RewardsItemRate[i] >> Engine->pCollectionRaceEvent.RandomID[i];

		if (Engine->pCollectionRaceEvent.RewardsItemID[i] == 900004000)
		{
			Engine->pCollectionRaceEvent.isRandom[i] = 1;
			// UYARI GİDERİLDİ: int 'i' değeri uint8'e dönüştürüldü
			Engine->pCollectionRaceEvent.RandomSlotID[i] = (uint8)i;
			Engine->CrRandomReward++;
		}
	}

	pkt >> Engine->pCollectionRaceEvent.EventTimer >> Engine->pCollectionRaceEvent.m_iCompleteUserCount >> Engine->pCollectionRaceEvent.TotalParticipantUser >> Engine->pCollectionRaceEvent.Nation;
	pkt >> Engine->pCollectionRaceEvent.EventName >> Engine->pCollectionRaceEvent.sZone;

	if (Engine->uiCollection != NULL)
		Engine->uiCollection->Start();
}

void CollectionRaceGetActiveTime(Packet& pkt)
{
	if (Engine->uiCollection == NULL)
		return;

	Engine->IsCRActive = true;
	Engine->CrRandomReward = 0;

	uint16 userkillcount = 0;
	for (int i = 0; i < 3; i++)
	{
		pkt >> Engine->pCollectionRaceEvent.sSid[i] >> Engine->pCollectionRaceEvent.killTarget[i] >> userkillcount;
		Engine->pCollectionRaceEvent.killCount[i] = userkillcount;
	}

	for (int i = 0; i < 10; i++)
	{
		pkt >> Engine->pCollectionRaceEvent.RewardsItemID[i] >> Engine->pCollectionRaceEvent.RewardsItemCount[i] >> Engine->pCollectionRaceEvent.RewardsItemRate[i] >> Engine->pCollectionRaceEvent.RandomID[i];

		if (Engine->pCollectionRaceEvent.RewardsItemID[i] == 900004000)
		{
			Engine->pCollectionRaceEvent.isRandom[i] = 1;
			// UYARI GİDERİLDİ: int 'i' değeri uint8'e dönüştürüldü
			Engine->pCollectionRaceEvent.RandomSlotID[i] = (uint8)i;
			Engine->CrRandomReward++;
		}
	}

	pkt >> Engine->pCollectionRaceEvent.EventTimer >> Engine->pCollectionRaceEvent.m_iCompleteUserCount >> Engine->pCollectionRaceEvent.TotalParticipantUser >> Engine->pCollectionRaceEvent.Nation;
	pkt >> Engine->pCollectionRaceEvent.EventName;

	if (Engine->m_UiMgr != NULL && Engine->uiCollection != NULL)
	{
		Engine->uiCollection->Open();
		Engine->uiCollection->Start();
		Engine->uiCollection->Update();
	}
}

void CollectionRaceHide()
{
	if (Engine->m_UiMgr != NULL && Engine->uiCollection != NULL)
		Engine->uiCollection->Close();
}

void CollectionRaceDead(Packet & pkt)
{


	if (Engine->m_UiMgr == NULL || Engine->uiCollection == NULL)
		return;



	uint16 MonsterProtoID, UserKillCount[3];
	pkt >> MonsterProtoID >> UserKillCount[0] >> UserKillCount[1] >> UserKillCount[2];

	if (Engine->IsCRActive)
	{

		bool updateRequired = false;
		for (int i = 0; i < 3; i++)
		{
			if (Engine->pCollectionRaceEvent.sSid[i] == MonsterProtoID)
			{
				if (Engine->pCollectionRaceEvent.killCount[i] < Engine->pCollectionRaceEvent.killTarget[i])
				{
					Engine->pCollectionRaceEvent.killCount[i] = UserKillCount[i];
					updateRequired = true;
				}
			}
		}

		if (updateRequired && Engine->m_UiMgr != NULL)
			Engine->uiCollection->Update();
	}
}

void CollectionRaceUpdateCounter(Packet & pkt)
{
	if (!Engine->IsCRActive || Engine->m_UiMgr == NULL || Engine->uiCollection == NULL)
		return;

	pkt >> Engine->pCollectionRaceEvent.m_iCompleteUserCount >> Engine->pCollectionRaceEvent.TotalParticipantUser;

	Engine->uiCollection->UpdateFinishUserCounter();
}

void CollectionRaceFinish()
{
	Engine->IsCRActive = false;
	Engine->CrRandomReward = 0;

	if (Engine->m_UiMgr != NULL && Engine->uiCollection != NULL)
		Engine->SetVisible(Engine->uiCollection->m_dVTableAddr, false);

	if (Engine->uiTopRightNewPlug != NULL)
		Engine->uiTopRightNewPlug->HideCollectionRaceButton();

	for (int i = 0; i < 3; i++)
	{
		Engine->pCollectionRaceEvent.sSid[i] = 0;
		Engine->pCollectionRaceEvent.killTarget[i] = 0;
		Engine->pCollectionRaceEvent.killCount[i] = 0;
	}
	for (int i = 0; i < 10; i++)
	{
		Engine->pCollectionRaceEvent.RewardsItemID[i] = 0;
		Engine->pCollectionRaceEvent.RewardsItemCount[i] = 0;
		Engine->pCollectionRaceEvent.RewardsItemRate[i] = 0;
	}

	Engine->pCollectionRaceEvent.EventTimer = 0;
	Engine->pCollectionRaceEvent.m_iCompleteUserCount = Engine->pCollectionRaceEvent.TotalParticipantUser = 0;
	Engine->pCollectionRaceEvent.EventName = "Collection Race Event";


	//Engine->uiCollection = NULL;
}

void HandleCastleSiegeWarTimer(Packet & pkt)
{
	pkt >> Engine->pCastleSiegeWar.SiegeType >> Engine->pCastleSiegeWar.StartTime >> Engine->pCastleSiegeWar.RemainingTime;
	pkt.SByte();
	pkt >> Engine->pCastleSiegeWar.SiegeOwnerClanName;

	//if (Engine->m_UiMgr->uiCastleSiegeWarSituation == NULL)
	if (Engine->uiTopRightNewPlug->BasladimiBaslamadimi == false)
	{
		Engine->uiTopRightNewPlug->BasladimiBaslamadimi = true;

		if (Engine->pCastleSiegeWar.SiegeType == 0x01)
			Engine->isSiegeWarStart = true;

		if (Engine->pCastleSiegeWar.SiegeType == 0x02)
		{
			Engine->isSiegeWarStart = false;
			Engine->isSiegeWarActive = true;
		}

		//test

	}

	if (Engine->pCastleSiegeWar.SiegeType == 0x00)
	{
		Engine->isSiegeWarStart = false;
		Engine->isSiegeWarActive = false;

		//test sildirme
		Engine->uiTopRightNewPlug->BasladimiBaslamadimi = false;
		if (Engine->uiTopRightNewPlug != NULL)
		{

		}
		//test


	}


}

bool voiceStarted = false;

void ZindanWarFlag(Packet & pkt) {
	std::string ename, kname;
	uint16 ekillcount, kkillcount; uint32 remtime;
	pkt >> ename >> ekillcount >> kname >> kkillcount >> remtime;
	if (ename.empty() || kname.empty() || !Engine->uiScoreBoard) return;

	if (!Engine->uiScoreBoard->m_Timer) Engine->uiScoreBoard->m_Timer = new CTimer(false);

	Engine->SetString(Engine->uiScoreBoard->Ename, ename);
	Engine->SetString(Engine->uiScoreBoard->Kname, kname);
	Engine->SetString(Engine->uiScoreBoard->EScore, std::to_string(ekillcount));
	Engine->SetString(Engine->uiScoreBoard->KScore, std::to_string(kkillcount));
	Engine->SetString(Engine->uiScoreBoard->RemTime, std::to_string(remtime));
	Engine->pzindanwar.start = true;
	Engine->pzindanwar.remtime = remtime;
	if (Engine->m_PlayerBase->m_iZoneID == 91) Engine->SetVisible(Engine->uiScoreBoard->m_dVTableAddr, true);
}

void ZindanWarLogOut() {
	if (Engine->uiScoreBoard) Engine->SetVisible(Engine->uiScoreBoard->m_dVTableAddr, false);
	Engine->pzindanwar.Init();
}

void ZindanWarUpdateScore(Packet & pkt) {
	uint8 nation; uint16 killcount;
	pkt >> nation >> killcount;
	if ((nation != 1 && nation != 2) || !Engine->uiScoreBoard) return;
	if (nation == 1) Engine->SetString(Engine->uiScoreBoard->KScore, std::to_string(killcount));
	else Engine->SetString(Engine->uiScoreBoard->EScore, std::to_string(killcount));
}

enum class ZindanOp { flagsend, updatescore, logout };
void HandleZindanWar(Packet & pkt) {
	uint8 subcode = pkt.read<uint8>();
	switch ((ZindanOp)subcode)
	{
	case ZindanOp::flagsend:
		ZindanWarFlag(pkt);
		break;
	case ZindanOp::updatescore:
		ZindanWarUpdateScore(pkt);
		break;
	case ZindanOp::logout:
		ZindanWarLogOut();
		break;
	}
}
int GetMsSinceMidnightGmt(std::chrono::system_clock::time_point tpNow) {
	time_t tnow = std::chrono::system_clock::to_time_t(tpNow);

	// UYARI GİDERİLDİ (C4189): Kullanılmayan 'tmDate' değişkeni silindi.

	std::chrono::duration<int> durTimezone; // 28800 for HKT
	// because mktime assumes local timezone, we shift the time now to GMT, then fid mid
	time_t tmid = std::chrono::system_clock::to_time_t(tpNow - durTimezone);
	tm* tmMid = std::localtime(&tmid);
	tmMid->tm_hour = 0;
	tmMid->tm_min = 0;
	tmMid->tm_sec = 0;
	auto tpMid = std::chrono::system_clock::from_time_t(std::mktime(tmMid));
	auto durSince = tpNow - durTimezone - tpMid;
	auto durMs = std::chrono::duration_cast<std::chrono::milliseconds>(durSince);

	// UYARI GİDERİLDİ: Dönüşüm int tipine zorlandı.
	return (int)durMs.count();
}

void HandleDailyQuests(Packet& pkt)
{
	uint8 subcode = 0;
	pkt >> subcode;

	switch (subcode)
	{
	case (uint8)DailyQuestOp::sendlist:
	{
		uint16 isize = 0;
		pkt >> isize;
		for (uint8 i = 0; i < isize; i++)
		{
			DailyQuest* quest = new DailyQuest();
			pkt >> quest->index >> quest->questtype >> quest->killtype;
			for (uint8 j = 0; j < 4; j++)
			{
				pkt >> quest->Mob[j] >> quest->KillTarget[j] >> quest->Reward[j] >> quest->Count[j];
			}
			pkt >> quest->ZoneID >> quest->replaytime >> quest->MinLevel >> quest->MaxLevel >> quest->strQuestName >> quest->premiumstatus;


			if (Engine->uiQuestPage)
				Engine->uiQuestPage->kcbq_quests.push_back(quest);

			//kcbq_quests.push_back(quest);
		}
		//if (Engine->uiQuestPage) Engine->m_UiMgr->kcbq_quests = Engine->uiQuestPage->kcbq_quests;
	}
	break;
	case (uint8)DailyQuestOp::userinfo:
	{
		uint16 isize = 0;
		pkt >> isize;
		for (uint8 i = 0; i < isize; i++)
		{
			uint8 id = 0;
			pkt >> id;

			uint8 status; uint16 mycount[4]; uint32 time;
			memset(mycount, 0, sizeof(mycount));
			pkt >> status;
			for (int a = 0; a < 4; a++)
				pkt >> mycount[a];

			pkt >> time;

			if (Engine->uiQuestPage)
			{
				// UYARI GİDERİLDİ (C4456): İsim çakışmasını önlemek için iç döngüdeki değişken 'qIdx' yapıldı.
				for (uint32 qIdx = 0; qIdx < Engine->uiQuestPage->kcbq_quests.size(); qIdx++)
				{
					if (Engine->uiQuestPage->kcbq_quests[qIdx]->index == id)
					{
						Engine->uiQuestPage->kcbq_quests[qIdx]->Status = status;
						for (int x = 0; x < 4; x++)
							Engine->uiQuestPage->kcbq_quests[qIdx]->MyCount[x] = mycount[x];

						Engine->uiQuestPage->kcbq_quests[qIdx]->remtime = time;
					}
				}
			}

		}
		if (Engine->uiQuestPage)
		{
			Engine->uiQuestPage->InitQuests();
		}

	}
	break;

	case (uint8)DailyQuestOp::killupdate:
	{
		uint8 questID;
		pkt >> questID;
		uint16 mobid;
		pkt >> mobid;
		if (Engine->uiQuestPage) Engine->uiQuestPage->KillTrigger(questID, mobid);
	}
	break;

	}
}
void HandleEventShowList(Packet& pkt) {
	if (!Engine || !Engine->m_UiMgr) return;

	Engine->m_UiMgr->m_eventshowlist.clear();

	pkt >> Engine->serverhour >> Engine->serverminute >> Engine->serversecond;

	uint16 sz = 0; pkt >> sz;
	if (!sz) return;

	for (int i = 0; i < sz; i++) {
		std::string eventName = "", time = ""; uint32 hour, minute; // UYARI GİDERİLDİ
		pkt >> eventName >> hour >> minute; // Değişken güncellendi
		if (eventName.empty()) continue; // Değişken güncellendi

		if (hour < 10) time.append(string_format("0%s:", to_string(hour).c_str()));
		else time.append(string_format("%s:", to_string(hour).c_str()));
		if (minute < 10) time.append(string_format("0%s", to_string(minute).c_str()));
		else time.append(string_format("%s", to_string(minute).c_str()));
		Engine->m_UiMgr->m_eventshowlist.push_back(EventShow(eventName, time, hour, minute)); // Değişken güncellendi
	}

	std::sort(Engine->m_UiMgr->m_eventshowlist.begin(),
		Engine->m_UiMgr->m_eventshowlist.end(), [](auto const& a, auto const& b) { return a.hour < b.hour && a.minute < b.minute; });

	int i = 0;
}

void HandleCindirella(Packet & pkt) {

	if (!Engine->uiCindirella)
		return;

	uint8 opcode = pkt.read<uint8>();
	switch ((cindopcode)opcode)
	{
	case cindopcode::selectclass:
	{
		uint8 result = pkt.read<uint8>();
		switch ((cindopcode)result)
		{
		case cindopcode::success:
		{
			uint8 index = pkt.read<uint8>();
			if (index > 4) return;

			Engine->uiCindirella->CharacterSelect(index);
		}
		break;
		case cindopcode::timewait:
		{
			uint32 remtime = pkt.read<uint32>();
			if (remtime)
				Engine->WriteInfoMessage((char*)string_format(xorstr("You have %d seconds to change it again"), remtime).c_str(), D3DCOLOR_ARGB(255, 255, 0, 255));
		}
		break;
		case cindopcode::notchange:
			Engine->WriteInfoMessage((char*)xorstr("You have not made any changes to your selections."), D3DCOLOR_ARGB(255, 255, 0, 255));
			break;
		case cindopcode::alreadyclass:
			Engine->WriteInfoMessage((char*)xorstr("same class please choose a different class."), D3DCOLOR_ARGB(255, 255, 0, 255));
			break;
		}
	}
	break;
	case cindopcode::nationchange:
	{
		uint8 result = pkt.read<uint8>();
		switch ((cindopcode)result)
		{
		case cindopcode::alreadynation:
			Engine->WriteInfoMessage((char*)xorstr("same nation please choose a different nation."), D3DCOLOR_ARGB(255, 255, 0, 255));
			break;
		case cindopcode::success:
			Engine->WriteInfoMessage((char*)xorstr("Nation selections applied successfully."), D3DCOLOR_ARGB(255, 255, 64, 89));
			break;
		case cindopcode::timewait:
		{
			uint32 remtime = pkt.read<uint32>();
			if (remtime)
				Engine->WriteInfoMessage((char*)string_format(xorstr("You have %d seconds to change it again"), remtime).c_str(), D3DCOLOR_ARGB(255, 255, 0, 255));
		}
		break;
		}
	}
	break;
	case cindopcode::joinevent:
	{
		uint32 tm = 0;
		pkt >> Engine->m_cindirellaInfo.prepare >> Engine->m_cindirellaInfo.index;
		pkt >> tm >> Engine->m_cindirellaInfo.mykill_count >> Engine->m_cindirellaInfo.mydead_count;
		pkt >> Engine->m_cindirellaInfo.k_kill_count >> Engine->m_cindirellaInfo.e_kill_count;

		Engine->uiCindirella->ison = true;
		Engine->m_cindirellaInfo.remainingtime = tm;

		Engine->uiCindirella->ShowPanel();
		if (!Engine->m_cindirellaInfo.prepare) Engine->uiCindirella->Start();

	}
	break;
	case cindopcode::starting:
	{
		uint32 tm = 0;
		pkt >> tm;

		if (!Engine->uiCindirella->ison) Engine->uiCindirella->ison = true;
		Engine->m_cindirellaInfo.remainingtime = tm;
		Engine->uiCindirella->Start();
		Engine->uiCindirella->Open();
	}
	break;
	case cindopcode::finish:
	{

		Engine->uiCindirella->Reset();
		Engine->uiCindirella->Close();

		if (Engine->uiTopRightNewPlug && Engine->IsVisible(Engine->uiTopRightNewPlug->m_cindirella))
			Engine->SetVisible(Engine->uiTopRightNewPlug->m_cindirella, false);
	}
	break;
	case cindopcode::updatekda:
	{
		uint8 set = pkt.read<uint8>();
		if (!set)
			pkt >> Engine->m_cindirellaInfo.mykill_count >> Engine->m_cindirellaInfo.mydead_count;
		else
			pkt >> Engine->m_cindirellaInfo.e_kill_count >> Engine->m_cindirellaInfo.k_kill_count;

		if (!Engine->uiCindirella || !Engine->uiCindirella->status || Engine->uiCindirella->prepare)
			return;

		Engine->uiCindirella->UpdateKDA();
	}
	break;
	default:
		break;
	}
}
void HandleCSW(Packet& pkt)
{
	enum class csw_flags
	{
		timer,
		finish
	};

	if (Engine->m_UiMgr->uiCSW == NULL)
	{
		std::string uifName = ""; // UYARI GİDERİLDİ
		uifName = Engine->dcpUIF(xorstr("BuhuR\\re_csw_timer.bbuhurr"));

		if (uifName.empty()) // Değişken güncellendi
			return;

		Engine->m_UiMgr->uiCSW = new CUICastleSiegeWar();
		Engine->m_UiMgr->uiCSW->Init(Engine->m_UiMgr);
		Engine->m_UiMgr->uiCSW->LoadFromFile(Engine->m_BasePath + uifName.c_str(), N3FORMAT_VER_1068); // Değişken güncellendi
		Engine->m_UiMgr->AddChild(Engine->m_UiMgr->uiCSW);
		remove(uifName.c_str()); // Değişken güncellendi
	}

	if (!Engine->m_UiMgr->uiCSW)
		return;

	uint8 subCode = pkt.read<uint8>();
	switch ((csw_flags)subCode)
	{
	case csw_flags::timer:
	{
		uint8 OpStatus;
		uint32 remtime, war_time; std::string knights_name;
		pkt.SByte();
		pkt >> remtime >> knights_name >> OpStatus >> war_time;
		if (remtime)
			Engine->m_UiMgr->uiCSW->setOptions(remtime, knights_name, OpStatus, war_time);
	}
	break;
	case csw_flags::finish:
	{
		if (Engine->m_UiMgr->uiCSW)
			Engine->m_UiMgr->uiCSW->Close();
	}
	default:
		break;
	}


	/*uint8 subcode = pkt.read<uint8>();
	if (subcode == 0)
	{
		if (Engine->m_UiMgr->uiCSW)
			Engine->m_UiMgr->uiCSW->setOptions(true);
		return;
	}

	uint32 remtime= 0;
	std::string owner_name = "";
	pkt >> remtime >> owner_name;



	Engine->m_UiMgr->uiCSW->setOptions(false, remtime, owner_name);*/
}

void HandleJuraidEvent(Packet & pkt)
{
	uint16 karus, elmos, remtime;
	pkt >> karus >> elmos >> remtime;
	if (remtime) Engine->OpenjuraidScreen(true, karus, elmos, remtime);
}

void HandlePerks(Packet & pkt)
{
	uint8 subcode = pkt.read<uint8>();
	switch ((perksSub)subcode)
	{
	case perksSub::info:
	{
		pkt >> Engine->pPerks.remPerk >> Engine->pPerks.perkCoins;
		uint16 size = 0;
		pkt >> size;

		for (int i = 0; i < size; i++) {
			_PERKS* p = new _PERKS();
			pkt.DByte();
			pkt >> p->pIndex >> p->status >> p->perkCount >> p->maxPerkCount >> p->strDescp >> p->percentage;
			auto itr = Engine->m_PerksArray.find(p->pIndex);
			if (itr == Engine->m_PerksArray.end())
				Engine->m_PerksArray.insert(std::make_pair(p->pIndex, p));
			else
				delete p;
		}

		for (int i = 0; i < PERK_COUNT; i++)
			pkt >> Engine->pPerks.perkType[i];
	}
	break;
	case perksSub::perkPlus:
	{
		if (Engine->uiState)
			Engine->uiState->perkPlus(pkt);
	}
	break;
	case perksSub::perkReset:
	{
		if (Engine->uiState)
			Engine->uiState->resetPerkPoint(pkt);
	}
	break;
	case perksSub::perkUseItem:
	{
		if (Engine->uiState)
			Engine->uiState->perkUseItem(pkt);
	}
	break;
	default:
		break;
	}
}

void HandleChestBlockItem()
{
	if (Engine->uiSearchMonster)Engine->uiSearchMonster->Reset();
}

void HandleSlave(Packet & pkt)
{
	uint8 opCode;
	pkt >> opCode;

	if (opCode == 1)//salve merchant
	{
		uint32 TotalKC, TotalCoins;
		// UYARI GİDERİLDİ: 'TotalTime' kullanılmadığı için silindi.
		uint8 subcode;
		uint32 sellinItem[12], MerchantItem[28];
		//...
		uint16 sellinItemCount[12], MerchantItemCount[28];

		for (int i = 0; i < 12; i++)
		{
			sellinItem[i] = 0;
			sellinItemCount[i] = 0;
		}

		for (int i = 0; i < 28; i++)
		{
			MerchantItem[i] = 0;
			MerchantItemCount[i] = 0;
		}

		Packet original = pkt;
		pkt >> subcode >> TotalKC >> TotalCoins;


		for (int i = 0; i < 12; i++)
			pkt >> sellinItem[i] >> sellinItemCount[i];

		for (int i = 0; i < 28; i++)
			pkt >> MerchantItem[i] >> MerchantItemCount[i];

		vector<SlaveItem> drops;
		if (drops.size())
			drops.clear();

		for (int i = 0; i < 12; i++) {
			drops.push_back(SlaveItem(sellinItem[i], sellinItemCount[i]));
		}


		vector<InventoryItem> drops2;
		if (drops2.size())
			drops2.clear();
		for (int i = 0; i < 28; i++)
			drops2.push_back(InventoryItem(MerchantItem[i], MerchantItemCount[i]));


		if (subcode == UPDATE_SLAVE_MERCHANT)
		{
			if (Engine->m_UiMgr->uiSlaveMerchant)
				Engine->m_UiMgr->uiSlaveMerchant->Update(original, drops, drops2);
		}
		else if (subcode == SLAVE_MERCHANT_PRICE)
		{
			if (Engine->m_UiMgr->uiSlaveMerchantPrice)
				Engine->m_UiMgr->uiSlaveMerchantPrice->Update(original);
		}
		else if (subcode == WANNA_OPEN_SLAVE_MERCHANT)
		{
			if (Engine->m_UiMgr->uiSlaveAccept == NULL) {
				Engine->m_UiMgr->OpenSlaveAccept();
			}
			else
			{
				if (Engine->m_UiMgr->uiSlaveAccept->IsVisible())
					Engine->m_UiMgr->uiSlaveAccept->Close();
				else
					Engine->m_UiMgr->uiSlaveAccept->Open();
			}
		}
		else if (subcode == SLAVE_MERCHANT_TIMEOUT)
		{
			Packet CloseMerc(XSafe, uint8(XSafeOpCodes::PL_SLAVE_MERC));
			CloseMerc << uint8(6) << uint8(0);
			Engine->Send(&CloseMerc);
		}
		else if (subcode == UPDATE_SLAVE_TIME)
		{
			if (Engine->m_UiMgr->uiSlaveMerchant)
				Engine->m_UiMgr->uiSlaveMerchant->UpdateTimer(original);
		}
	}
}

void __cdecl XSafeHandlePacket(Packet pkt)
{
	uint8_t SubOpCode;
	pkt >> SubOpCode;
	switch (SubOpCode)
	{
	case XSafeOpCodes::RECONNECT:
	{
		uint8 requestType = 0;
		pkt >> requestType;
		if (requestType == 1)
		{
			pkt >> reconnectToken;
			pkt.SByte();
			pkt >> reconnectAccount >> reconnectCharacter;
			reconnectAcked = false;
			SendReconnectDiscovery();
		}
		else if (requestType == 3)
		{
			uint8 result = 0;
			pkt >> result;
			reconnectAcked = result == 1;
		}
		else if (requestType == 5)
		{
			// Server planlı disconnect testi başlattı → reconnect panelini göster.
			// Karakter RECONNECT_TEST_HOLD_SECONDS boyunca oyunda askıda kalır.
			//
			// Premium güvenlik kapısı: sunucu token dağıtmadıysa (premium hakkı
			// olmayan oyuncu) panel hiç açılmaz. Reconnect yalnızca premium
			// oyunculara tanınır; tokensiz panel açılırsa "Yes/No" yanıtları
			// sunucuya gönderilemez (bkz. SendReconnectHoldResponse) ve oyuncu
			// yanıtsız panelde sıkışırdı.
			if (reconnectToken == 0)
			{
				printf("[RECONNECT] UI trigger ignored: no token (premium required)\n");
				break;
			}

			reconnectUiHoldSeconds = 0;
			pkt >> reconnectUiHoldSeconds;
			InterlockedExchange(&reconnectTestDisconnecting, 0);
			InterlockedExchange(&reconnectHoldExpired, 0);
			reconnectUiMode = RECONNECT_UI_HOLD;
			// YENİ TEST TETİKLENDİ: bir önceki oturumdan kalan "panel açık"
			// bayrağı ve render-önbelleği sıfırlanır. Aksi halde open-guard'daki
			// `reconnectUiShown` kontrolü bayrak takılı kalırdı ve 2. /reconnecttest
			// paneli hiç render edilmezdi. Kutu hâlâ açıksa render thread
			// ShowMessageBox → uiMsgBox->Update() ile yerinde günceller.
			reconnectUiShown = false;
			reconnectUiLastRenderedMode = -1;
			reconnectUiLastRenderedSecond = -1;
			reconnectUiPendingTime = GetTickCount();
			InterlockedExchange(&reconnectUiPending, 1);
		}
		else if (requestType == 9)
		{
			// Planlı disconnect ŞİMDİ uygulanıyor (süre doldu veya "disconnect now").
			// Köprü devre dışı bırakılır; oyunun kendi disconnect paneli normal
			// şekilde açılır. Panel seçenekleri devre dışı: karakter her durumda
			// oyundan düşürülür.
			InterlockedExchange(&reconnectTestDisconnecting, 1);
			InterlockedExchange(&reconnectHoldExpired, 1);
			reconnectUiMode = RECONNECT_UI_LOST;
			// Bekleme paneli açıksa kapat (render thread yapar): oyunun kendi
			// disconnect paneli engellenmesin.
			InterlockedExchange(&reconnectUiClosePending, 1);
		}
		else if (requestType == 7)
		{
			// Onay sonucu (oyun soketi yolu): 1 = kabul -> panel kapanır, askı
			// biter ve karakter oyunda kalır. 0 = reddedildi -> panel açık kalır,
			// süre dolduğunda normal disconnect akışı çalışır.
			uint8 result = 0;
			pkt >> result;
			reconnectStayAcked = result == 1;
			printf("[RECONNECT] confirm ack via game socket result=%u\n", result);
			if (result == 1)
			{
				InterlockedExchange(&reconnectHoldExpired, 0);
				InterlockedExchange(&reconnectTestDisconnecting, 0);
				InterlockedExchange(&reconnectUiClosePending, 1);
			}
		}
		else if (requestType == 11)
		{
			// Sunucu reconnect hakkını iptal etti (premium düştü ya da hiç yok).
			// Token temizlenir: kopma anında RecvDetour/SendDetour token
			// gate'i köprüyü TETİKLEMEZ ve oyuncu doğrudan normal disconnect
			// akışına düşer — reconnect paneli asla açılmaz.
			reconnectToken = 0;
			reconnectAccount.clear();
			reconnectCharacter.clear();
			reconnectAcked = false;
			reconnectStayAcked = false;
			InterlockedExchange(&reconnectUiPending, 0);
			InterlockedExchange(&reconnectUiClosePending, 1);
			printf("[RECONNECT] token revoked by server (premium required)\n");
		}
	}
	break;
	case XSafeOpCodes::PL_USER_TOOLS:
		HandleSlave(pkt);
		break;
	case XSafeOpCodes::CHEST_BLOCKITEM:
		HandleChestBlockItem();
		break;
	case XSafeOpCodes::PERKS:
		HandlePerks(pkt);
		break;
	case XSafeOpCodes::CSW:
		HandleCSW(pkt);
		break;
	case XSafeOpCodes::JURAID:
		HandleJuraidEvent(pkt);
		break;
	case XSafeOpCodes::CINDIRELLA:
		HandleCindirella(pkt);
		break;
	case XSafeOpCodes::RESET:
		Engine->Player.moneyreq = pkt.read<uint32>();
		break;
	case XSafeOpCodes::EventShowList:
		HandleEventShowList(pkt);
		break;
	case XSafeOpCodes::DAIL_QUESTS_1098:
		HandleDailyQuests(pkt);
		break;
	case XSafeOpCodes::ZindanWar:	// Zindanwar score board
		HandleZindanWar(pkt);
		break;
	case XSafeOpCodes::TOPLEFT:
		if (Engine->uiHpMenuPlug != NULL)
			Engine->uiHpMenuPlug->UpdateHpMenuVisible(pkt);
		break;
	case XSafeOpCodes::BANSYSTEM:
		banSystem->SetBan();
		break;
	case XSafeOpCodes::RIGHT_CLICK_EXCHANGE:
		if (Engine->hkRightClickExchange != NULL)Engine->hkRightClickExchange->RightClickExchangePacket(pkt);
		break;
	case XSafeOpCodes::MESSAGE2:
	{
		uint8 type, time;
		std::string title, message;
		uint32 colour;
		pkt.DByte();
		pkt >> type;

		if (type == (uint8)infomessageop::box) {
			pkt >> title >> message >> time;
			if (title.empty() || message.empty())
				return;

			Engine->m_UiMgr->ShowMessageBox(title, message, MsgBoxTypes::Ok);
		}
		else if (type == (uint8)infomessageop::infobar) {
			pkt >> message >> colour;
			if (message.empty())
				return;

			Engine->WriteInfoMessageExt((char*)string_format(message).c_str(), colour);
		}
	}
	break;
	// target Scroll Bar Eklemesi 03.02.2024
	case XSafeOpCodes::PKT_HOOK_TARGET_SCROLL:
	{
		uint8_t OpCode;
		pkt >> OpCode;
		if (OpCode == 1)
		{
			Engine->uiTargetBar->Update(pkt);
		}
	}
	break;
	// target Scroll Bar Eklemesi 03.02.2024 end
	case XSafeOpCodes::LOTTERY:
	{
		uint8 subcode;
		pkt >> subcode;
		if (Engine->uiLottery == NULL)
		{
			return;

		}

		if (Engine->uiLottery != NULL)
		{
			if (subcode == 1) // baslatma
			{
				if (!Engine->IsVisible(Engine->uiLottery->m_dVTableAddr))
				{
					Engine->uiLottery->OpenLottery();
				}

				Engine->SetState(Engine->uiLottery->btn_join, UI_STATE_BUTTON_NORMAL);

				uint32 reqItems[5] = { 0 }, reqItemsCount[5] = { 0 }, rewardItems[4] = { 0 };
				uint32 remainingTime = 0;
				uint32 partLimit = 0;
				uint32 participant = 0;
				uint32 ticketID = 0;

				for (int i = 0; i < 5; i++)
					pkt >> reqItems[i] >> reqItemsCount[i];
				for (int i = 0; i < 4; i++)
					pkt >> rewardItems[i];

				pkt >> partLimit >> remainingTime >> participant >> ticketID;

				Engine->lotteryEvent.limit = partLimit;
				Engine->lotteryEvent.participant = participant;
				Engine->lotteryEvent.remainingTime = remainingTime;

				float per = 0.0f;
				// UYARI VE MANTIK HATASI GİDERİLDİ: Tamsayı bölmesi yüzünden 0 çıkma hatası çözüldü
				if (Engine->lotteryEvent.participant > 0)
					per = (1.0f / (float)Engine->lotteryEvent.participant) * 100.0f;
				else
					per = 100.0f;

				//Engine->SetString(Engine->uiLottery->str_change,string_format(xorstr("%.3f%%"), per));
				Engine->SetString(Engine->uiLottery->str_participant, string_format(xorstr(" %d / %d"), participant, partLimit));
				if (ticketID == 0)
					Engine->SetString(Engine->uiLottery->str_ticket, xorstr("-"));
				else {
					Engine->SetString(Engine->uiLottery->str_ticket, string_format(xorstr("#%d"), ticketID));
					Engine->SetState(Engine->uiLottery->btn_join, UI_STATE_BUTTON_DISABLE);
				}

				/*for (int i = 0; i < 5; i++) */
				Engine->SetString(Engine->uiLottery->ticket_buy_count, string_format(xorstr("%d"), reqItemsCount[0]));
				Engine->uiLottery->Update(reqItems, reqItemsCount, rewardItems);
			}
			else if (subcode == 2) // katilimci güncellemesi
			{
				Engine->lotteryEvent.participant++;
				float per = 0.0F;

				// UYARI VE MANTIK HATASI GİDERİLDİ: Float tipine dönüştürüldü
				if (Engine->lotteryEvent.participant > 0)
					per = (1.0f / (float)Engine->lotteryEvent.participant) * 100.0f;
				else
					per = 100.0f;

				//Engine->SetString(Engine->uiLottery->str_change,string_format(xorstr("%.3f%%"), per));
				Engine->SetString(Engine->uiLottery->str_participant, string_format(xorstr(" %d / %d"), Engine->lotteryEvent.participant, Engine->lotteryEvent.limit));
			}
			else if (subcode == 3) // join
			{
				uint8 ok = 0;
				uint32 ticket = 0;
				pkt >> ok;
				if (ok == 1)
				{
					pkt >> ticket;
					//Engine->m_UiMgr->uiLottery->btn_join->SetState(UI_STATE_BUTTON_DISABLE);
					Engine->SetString(Engine->uiLottery->str_ticket, string_format(xorstr("#%d"), ticket));
					Engine->m_UiMgr->ShowMessageBox(xorstr("Lottey Event"), "You have successfully participated in the event.", MsgBoxTypes::Ok);
				}
				else {
					std::string msg = "";
					pkt >> msg;
					Engine->m_UiMgr->ShowMessageBox(xorstr("Error"), msg, MsgBoxTypes::Ok);
				}
			}
			else if (subcode == 4) // end
			{
				uint32 reqItems[5] = { 0 }, reqItemsCount[5] = { 0 }, rewardItems[4] = { 0 };
				Engine->lotteryEvent.limit = 0;
				Engine->lotteryEvent.participant = 0;
				Engine->lotteryEvent.remainingTime = 0;

				/*for (int i = 0; i < 5;i++) */
				Engine->SetString(Engine->uiLottery->ticket_buy_count, xorstr("-"));
				//Engine->SetString(Engine->uiLottery->str_change,xorstr("0%"));
				Engine->SetString(Engine->uiLottery->str_participant, string_format(xorstr(" %d / %d"), 0, 0));
				Engine->SetString(Engine->uiLottery->str_ticket, xorstr("-"));
				Engine->SetState(Engine->uiLottery->btn_join, UI_STATE_BUTTON_NORMAL);
				Engine->uiLottery->Update(reqItems, reqItemsCount, rewardItems, true);

				if (Engine->IsVisible(Engine->uiLottery->m_dVTableAddr))
				{
					Engine->uiLottery->Close();
				}

				if (Engine->uiTopRightNewPlug != NULL)
				{
					if (!Engine->IsVisible(Engine->uiTopRightNewPlug->m_lottery) && Engine->uiTopRightNewPlug->m_lottery)
					{
						Engine->SetVisible(Engine->uiTopRightNewPlug->m_lottery, false);
						Engine->SetState(Engine->uiTopRightNewPlug->m_lottery, UI_STATE_BUTTON_DISABLE);
					}
				}
			}
		}
	}
	break;
	case XSafeOpCodes::ERRORMSG: //30.08.2020
	{
		uint8 subcode;
		pkt >> subcode;

		if (subcode == 1) // join
		{
			uint8 ok = 0;
			uint32 ticket = 0;
			pkt >> ok;
			if (ok == 1)
			{
				std::string msgtitle = "", msg = "";
				pkt.DByte();
				pkt >> msgtitle >> msg;
				Engine->m_UiMgr->ShowMessageBox(msgtitle, msg, MsgBoxTypes::Ok);
			}
		}
	}
	break;
	case XSafeOpCodes::RankSymbol:
	{
		if (Engine->uiPlayerRank == NULL)
			break;
		Engine->uiPlayerRank->ResetBase();
		// UYARI GİDERİLDİ: 'Rank' değişkeni kullanılmadığı için silindi.
		uint8 Nation;
		uint16 sCount = 0;
		pkt >> Nation >> sCount;
		//...
		if (Nation == 2) {

			for (int i = 0; i < sCount; i++) {
				uint8 byRank;
				pkt >> byRank;
				if (byRank > 0) {
					printf("symbol_us\\s_0_%d_0.dxt \n", byRank);
					Engine->SetTexImage(Engine->uiPlayerRank->nHumanBase[i], string_format("symbol_us\\s_0_%d_0.dxt", byRank));
					Engine->SetVisible(Engine->uiPlayerRank->nHumanBase[i], true);
					Engine->SetVisible(Engine->uiPlayerRank->nHumanBaseEffeckt[i], true);
				}

			}
		}
		pkt >> Nation >> sCount;
		if (Nation == 1) {

			for (int i = 0; i < sCount; i++) {
				uint8 byRank;
				pkt >> byRank;
				if (byRank > 0) {
					printf("symbol_us\\s_0_%d_0.dxt \n", byRank);
					Engine->SetTexImage(Engine->uiPlayerRank->nKarusBase[i], string_format("symbol_us\\s_0_%d_0.dxt", byRank));

					Engine->SetVisible(Engine->uiPlayerRank->nKarusBase[i], true);
					Engine->SetVisible(Engine->uiPlayerRank->nKarusBaseEffeckt[i], true);
				}

			}
		}
		pkt >> Nation >> sCount;
		if (Nation == 3) {

			for (int i = 0; i < sCount; i++) {
				uint32 nItemID;
				uint16 nCount;
				pkt >> nItemID >> nCount;
				if (nItemID > 0 && Engine->uiPlayerRank)
				{
					DWORD baseCreateIcon = 0x00;
					Engine->_InitIcon(baseCreateIcon, Engine->uiPlayerRank->image_reward[i], nItemID);
					Engine->SetRegion(baseCreateIcon, Engine->uiPlayerRank->image_reward[i]);
					Engine->SetVisible(baseCreateIcon, true);
					Engine->uiPlayerRank->RankRewardItemList[i] = nItemID;
					Engine->SetString(Engine->uiPlayerRank->reward_count[i], std::to_string(nCount));
				}

			}
		}
	}
	break;
	case XSafeOpCodes::MESSAGE:
	{
		string title, message;
		pkt >> title >> message;

		if (Engine->m_UiMgr != NULL && !title.empty() && !message.empty() && title.length() <= 30 && message.length() <= 255)
			Engine->m_UiMgr->ShowMessageBox(title, message, MsgBoxTypes::Ok);
	}
	break;
	case XSafeOpCodes::MERCHANTLIST:
		Engine->m_UiMgr->ShowMerchantList(pkt);
		break;
	case XSafeOpCodes::RPGUARD_AUTO_UPGRADE:
		Engine->m_UiMgr->ShowAutoUpList(pkt);
		break;
	case XSafeOpCodes::REBIRTH_UIF:
	{
		uint8 OpCode;
		pkt >> OpCode;

		if (OpCode == 1)
		{
			if (Engine->m_UiMgr->uiRebith == NULL)//
			{
				std::string uifName = ""; // UYARI GİDERİLDİ
				uifName = Engine->dcpUIF(xorstr("BuhuR\\re_rebirthsystem.bbuhurr"));
				Engine->m_UiMgr->uiRebith = new CRebith();
				Engine->m_UiMgr->uiRebith->Init(Engine->m_UiMgr);
				Engine->m_UiMgr->uiRebith->LoadFromFile(Engine->m_BasePath + uifName.c_str(), N3FORMAT_VER_1068); // Değişken güncellendi
				Engine->m_UiMgr->AddChild(Engine->m_UiMgr->uiRebith);
				remove(uifName.c_str()); // Değişken güncellendi
			}
			else
			{
				if (Engine->m_UiMgr->uiRebith->IsVisible())
					Engine->m_UiMgr->uiRebith->Close();
				else
					Engine->m_UiMgr->uiRebith->Open();
			}
		}
	}break;
	case PL_SLAVE_PRIEST_OPCODE:
	{
		uint8 opCode;
		pkt >> opCode;
		if (opCode == 1)
		{
			if (Engine->m_UiMgr->uiSlavePriestSub == NULL)
			{
				Engine->m_UiMgr->uiSlavePriestSub = new UISlavePriestSub();
				Engine->m_UiMgr->uiSlavePriestSub->Init(Engine->m_UiMgr);
				Engine->m_UiMgr->uiSlavePriestSub->LoadFromFile(Engine->m_BasePath + xorstr("BuhuR\\DAT-7.uif"), N3FORMAT_VER_1068);
				Engine->m_UiMgr->AddChild(Engine->m_UiMgr->uiSlavePriestSub);
			}
			if (Engine->m_UiMgr->uiSlavePriestSub != NULL)
				if (!Engine->m_UiMgr->uiSlavePriestSub->IsVisible())
					Engine->m_UiMgr->uiSlavePriestSub->Open();
		}
		else if (opCode == 2)
		{
			if (Engine->m_UiMgr->uiSlavePriestSub != NULL)
				if (Engine->m_UiMgr->uiSlavePriestSub->IsVisible())
					Engine->m_UiMgr->uiSlavePriestSub->Close();
		}
	}
	break;
	case PL_VS_EVENT:
	{
		Packet original = pkt;

		if (Engine->m_UiMgr->uiVsKabul == NULL)
		{
			std::string uifName = Engine->dcpUIF(xorstr("BuhuR\\1vs1.bbuhurr")); // UYARI GİDERİLDİ
			Engine->m_UiMgr->uiVsKabul = new CVsKabul();
			Engine->m_UiMgr->uiVsKabul->Init(Engine->m_UiMgr);
			Engine->m_UiMgr->uiVsKabul->LoadFromFile(Engine->m_BasePath + uifName.c_str(), N3FORMAT_VER_1068); // Değişken güncellendi
			Engine->m_UiMgr->AddChild(Engine->m_UiMgr->uiVsKabul);
			remove(uifName.c_str()); // Değişken güncellendi
			if (Engine->m_UiMgr->uiVsKabul != NULL)
			{
				Engine->m_UiMgr->uiVsKabul->Open();
				Engine->m_UiMgr->uiVsKabul->Update(original);
			}
		}
		else
		{
			if (!Engine->m_UiMgr->uiVsKabul->IsVisible())
			{
				Engine->m_UiMgr->uiVsKabul->Open();
				Engine->m_UiMgr->uiVsKabul->Update(original);
			}

		}
	}break;
	case XSafeOpCodes::AUTODROP:
	{
		uint8 type;
		uint32 nItemID;
		pkt >> type >> nItemID;

		if (!Engine->m_bGameStart || Engine->m_UiMgr == NULL)
			return;

		if (type == 0) // auto mining
		{
			if (Engine->uiDropResult != NULL) {
				Engine->m_UiMgr->ShowDropResult();
				Engine->SetVisible(Engine->uiDropResult->m_dVTableAddr, false);
			}

			Engine->uiDropResult->SetTitle("Auto Mining");
			Engine->uiDropResult->AddItem(nItemID);

			TABLE_ITEM_BASIC* item = Engine->tblMgr->getItemData(nItemID);
			if (item != nullptr)
				Engine->WriteInfoMessage((char*)string_format(xorstr("[Mining] you received %s"), item->strName.c_str()).c_str(), 0xFFF2AB);

			Engine->uiTopRightNewPlug->DropResultStatus(true);
		}
		else if (type == 1) // auto fishing
		{
			/*if (Engine->m_UiMgr->uiDropResult == NULL) {
				Engine->m_UiMgr->ShowDropResult();
				Engine->m_UiMgr->uiDropResult->SetVisible(false);
			}*/

			Engine->uiDropResult->SetTitle("Auto Fishing");
			Engine->uiDropResult->AddItem(nItemID);

			TABLE_ITEM_BASIC* item = Engine->tblMgr->getItemData(nItemID);
			if (item != nullptr)
				Engine->WriteInfoMessage((char*)string_format(xorstr("[Fishing] you received %s"), item->strName.c_str()).c_str(), 0xFFF2AB);

			Engine->uiTopRightNewPlug->DropResultStatus(true);
		}
		else if (type == 2)
		{
			if (Engine->uiDropResult != NULL)
			{
				Engine->uiDropResult->Close();
				Engine->uiTopRightNewPlug->DropResultStatus(false);
			}
		}
		else if (type == 3) // wheel of fun
		{
			if (Engine->uiWheel != NULL)
			{
				Engine->uiWheel->StopChallange();

				Engine->uiWheel->GiveItemImage(nItemID);

			}
		}
		else if (type == 4) // cind warehouse
		{
			TABLE_ITEM_BASIC* item = Engine->tblMgr->getItemData(nItemID);
			if (item != nullptr)
			{
				auto pItemExt = Engine->tblMgr->getExtData(item->extNum, nItemID);
				if (pItemExt && pItemExt->szHeader.size() > 1)
					Engine->WriteInfoMessage((char*)string_format(xorstr("[Warehouse (Inn)] you received %s"), pItemExt->szHeader.c_str()).c_str(), 0xFFF2AB);
				else
					Engine->WriteInfoMessage((char*)string_format(xorstr("[Warehouse (Inn)] you received %s"), item->strName.c_str()).c_str(), 0xFFF2AB);
			}
		}
		else if (type == 23)
		{
			if (nItemID == 0)
			{
				if (Engine->uiDropResult != NULL)
				{
					Engine->uiDropResult->CloseUp();

					if (Engine->uiTopRightNewPlug != NULL)
					{
						Engine->uiTopRightNewPlug->AutoUpStatus(false);
						//if (Engine->uiTopRightNewPlug->upstatusx)
						//{
						//	Engine->uiTopRightNewPlug->upstatusx = false;
						//	Engine->uiTopRightNewPlug->AutoUpStatus(false);
						//}
					}
				}
			}
			else
			{
				if (Engine->uiTopRightNewPlug != NULL)
				{
					Engine->uiTopRightNewPlug->AutoUpStatus(true);
					//if (!Engine->uiTopRightNewPlug->upstatusx)
					//{
					//	//Engine->uiTopRightNewPlug->upstatusx = true;
					//	Engine->uiTopRightNewPlug->AutoUpStatus(true);
					//}
				}
			}
		}
		else
		{
			if (Engine->uiDropResult != NULL)
			{
				Engine->uiDropResult->Close();
				Engine->uiTopRightNewPlug->DropResultStatus(false);
			}
			Engine->WriteInfoMessageExt((char*)xorstr("[Mining/Fishing] stopped"), 0xFFF2AB);
		}
	}
	break;
	case XSafeOpCodes::KCUPDATE:
	{
		uint32 cash, tl_balance;
		pkt >> cash >> tl_balance;

		Engine->Player.KnightCash = cash;
		Engine->Player.TlBalance = tl_balance;
		if (Engine->uiState != NULL)
		{
			Engine->uiState->m_iBalance = tl_balance;
			Engine->uiState->m_iCash = cash;
			Engine->uiState->UpdateUI();
		}

		if (Engine->uiTradeInventory != NULL)
			Engine->uiTradeInventory->UpdateTotal(cash);

		if (Engine->uiPowerUpStore != NULL)
			Engine->uiPowerUpStore->UpdateCash(cash, tl_balance);
	}
	case XSafeOpCodes::USERDATA:
	{
		if (Engine->m_PlayerBase != NULL)
			Engine->m_PlayerBase->Update(pkt);
	}
	break;
	case XSafeOpCodes::CR:
	{
		HandleCollectionRace(pkt);
	}
	break;
	case XSafeOpCodes::DROP_REQUEST:
	case XSafeOpCodes::DROP_LIST:
		Engine->m_UiMgr->ShowDropList(pkt);
		break;
	case XSafeOpCodes::CASHCHANGE:
	{
		uint32 cash, tlbalance;
		pkt >> cash >> tlbalance;

		if (Engine->uiState != NULL)
		{
			// UYARI GİDERİLDİ: m_iCash ve m_iBalance (işaretli) değerleri, cash (uint32) ile kıyaslanırken uint32'ye cast edildi.
			if (cash > (uint32)Engine->uiState->m_iCash)
				Engine->WriteInfoMessageExt((char*)string_format(xorstr("Received %u knight cash."), cash - (uint32)Engine->uiState->m_iCash).c_str(), 0xFFF2AB);
			else if (cash < (uint32)Engine->uiState->m_iCash)
				Engine->WriteInfoMessageExt((char*)string_format(xorstr("Lost %u knight cash."), (uint32)Engine->uiState->m_iCash - cash).c_str(), 0xFF0000);

			if (tlbalance > (uint32)Engine->uiState->m_iBalance)
				Engine->WriteInfoMessageExt((char*)string_format(xorstr("Received %u tl balance."), tlbalance - (uint32)Engine->uiState->m_iBalance).c_str(), 0xFFF2AB);
			else if (tlbalance < (uint32)Engine->uiState->m_iBalance)
				Engine->WriteInfoMessageExt((char*)string_format(xorstr("Lost %u tl balance."), (uint32)Engine->uiState->m_iBalance - tlbalance).c_str(), 0xFF0000);
		}

		Engine->Player.KnightCash = cash;
		Engine->Player.TlBalance = tlbalance;
		if (Engine->uiState != NULL)
		{
			Engine->uiState->m_iCash = cash;
			Engine->uiState->m_iBalance = tlbalance;
			Engine->uiState->UpdateUI();
		}
		if (Engine->uiWheel != NULL)
			Engine->SetString(Engine->uiWheel->KnightCash, string_format("Knight Cash : %d", cash).c_str());

		if (Engine->uiTradeInventory != NULL)
			Engine->uiTradeInventory->UpdateTotal(cash);

		if (Engine->uiPowerUpStore != NULL)
			Engine->uiPowerUpStore->UpdateCash(cash, tlbalance);
	}
	break;
	case XSafeOpCodes::INFOMESSAGE:
	{
		string message;
		pkt >> message;
		Engine->WriteInfoMessageExt((char*)message.c_str(), 0xFFF2AB);
	}
	break;
	case XSafeOpCodes::PUS:
	{
		vector<PUSItem> PusItems;

		uint32_t PusItemCount = pkt.read<uint32_t>();
		for (uint32 i = 0; i < PusItemCount; i++)
		{
			uint32 sID, sItemID, sPrice, sQuantitiy;
			uint8 sCategory, isTlBalance;


			pkt >> sID >> sItemID >> sPrice >> sCategory >> sQuantitiy >> isTlBalance;

			PusItems.push_back(PUSItem(sID, sItemID, sPrice, isTlBalance, (PUS_CATEGORY)sCategory, sQuantitiy));
		}

		pusINIT = true;
		Engine->m_UiMgr->item_list = PusItems;
	}
	break;
	case XSafeOpCodes::PusCat:
	{
		vector<PusCategory> Puscats;

		uint32_t CategortyCount = pkt.read<uint32_t>();
		for (uint32 i = 0; i < CategortyCount; i++)
		{
			uint32 sID;
			uint8 isVisible;
			std::string catename;
			pkt >> sID >> catename >> isVisible;
			Puscats.push_back(PusCategory(sID, catename, isVisible));
		}

		pusINIT = true;
		Engine->m_UiMgr->cat_list = Puscats;
	}
	break;
	case XSafeOpCodes::PROCINFO:
	{
		uint16 toWHO = 0;
		pkt >> toWHO;
		LM_SendProcess(toWHO);
	}
	break;
	case XSafeOpCodes::SkillQuest:
	{
		uint16 sQuestID;

		pkt >> sQuestID;
		std::map<uint32, CSpell>::iterator itr;
		for (itr = Engine->skillmap.begin(); itr != Engine->skillmap.end(); itr++)
		{
			if (CSpell* spell = GetSkillBase(itr->second.dwID))
				if (spell->iIDK2 == 390)
					spell->iIDK2 = 0;
		}
	}
	break;
	case XSafeOpCodes::OPEN:
	{
		string address;
		pkt >> address;
		ShellExecuteA(NULL, xorstr("open"), address.c_str(), NULL, NULL, SW_SHOWNORMAL);
	}
	break;
	case XSafeOpCodes::UIINFO:
	{
		if (!Engine->m_bHookStart) {
			StartHook();
		}

		uint32 cash, moneyreq, tlbalance;
		int64 exp, maxexp;
		uint16 dd, axe, sword, mace, spear, bow, jamadar;
		pkt >> cash >> tlbalance >> dd >> axe >> sword >> mace >> spear >> bow >> jamadar >> moneyreq >> exp >> maxexp;

#if (HOOK_SOURCE_VERSION == 1098)
		if (Engine->uiHPBarPlug != NULL) {
			Engine->uiHPBarPlug->MaxExp = maxexp;
			Engine->uiHPBarPlug->ExpChange(exp, maxexp);
		}
#endif

		Engine->Player.KnightCash = cash;
		Engine->Player.TlBalance = tlbalance;
		Engine->moneyReq = moneyreq;

		if (Engine->m_PlayerBase == NULL)
			Engine->m_PlayerBase = new CPlayerBase();

		uint16 m_iSocketID;

		std::string m_strCharacterName;
		short m_sClass;
		uint8 m_iRace;
		uint8 m_iLevel;

		uint8 m_iStr;
		uint8 m_iHp;
		uint8 m_iDex;
		uint8 m_iInt;
		uint8 m_iMp;

		pkt >> m_iSocketID;
		pkt.DByte();
		pkt >> m_strCharacterName >> m_sClass >> m_iRace >> m_iLevel
			>> m_iStr >> m_iHp >> m_iDex >> m_iInt >> m_iMp;

		tagName tag;
		pkt >> tag.tag >> tag.r >> tag.g >> tag.b; // tagrenk

		pkt >> Engine->Player.ZoneID >> Engine->Player.burninglevel;

		if (Engine->Player.burninglevel && Engine->uiHPBarPlug != NULL)
			Engine->uiHPBarPlug->BurningChange(Engine->Player.burninglevel);

		Packet UserInformation;
		UserInformation << m_iSocketID << m_strCharacterName << m_sClass << m_iRace << m_iLevel << m_iStr << m_iHp << m_iInt << m_iMp;

		if (Engine->m_PlayerBase != NULL)
			Engine->m_PlayerBase->Update(UserInformation);

		if (Engine->uiState != NULL)
		{
			// dd >> axe >> sword >> mace >> spear >> bow >> jamadar >>
			Engine->uiState->m_iCash = cash;
			Engine->uiState->m_iBalance = tlbalance;
			Engine->uiState->m_iDagger = dd;
			Engine->uiState->m_iAxe = axe;
			Engine->uiState->m_iSword = sword;
			Engine->uiState->m_iClub = mace;
			Engine->uiState->m_iSpear = spear;
			Engine->uiState->m_iArrow = bow;
			Engine->uiState->m_iJamadar = jamadar;
			Engine->uiState->UpdateUI();
		}

		//if (Engine->uiTradeInventory != NULL) Engine->uiTradeInventory->UpdateTotal(cash);
		if (!tag.tag.empty() && tag.tag != "-")
			Engine->addnewtagid(m_iSocketID, tag);

		uiINIT = true;
	}
	break;
	case XSafeOpCodes::MERC_WIEWER_INFO:
	{
		uint8 subCode;
		std::string Name;
		uint8 saat, dakika;
		pkt.SByte();
		pkt >> subCode >> Name >> saat >> dakika;
		switch (subCode)
		{
		case 1:
			// UYARI GİDERİLDİ: -1 yerine 0xFFFFFFFF kullanıldı.
			Engine->WriteInfoMessageExt((char*)string_format(xorstr("%s visited your merchant at %02d:%02d"), Name.c_str(), saat, dakika).c_str(), 0xFFFFFFFF);
			break;
		case 2:
			// UYARI GİDERİLDİ: -1 yerine 0xFFFFFFFF kullanıldı.
			Engine->WriteInfoMessageExt((char*)string_format(xorstr("%s left your merchant at %02d:%02d"), Name.c_str(), saat, dakika).c_str(), 0xFFFFFFFF);
			break;
		}
	}break;
	case XSafeOpCodes::DeathNotice:
	{
		uint8 sType;
		std::string kill;
		std::string Death;
		uint16 X, Z;
		pkt.SByte();
		pkt >> sType >> kill >> Death >> X >> Z;

		if (Engine->DeathNone)
			break;
		if (Engine->DeathAll)
		{
			if (sType == 1)
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 254, 128, 254), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());
			else if (sType == 2)
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 197, 209, 189), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());
			else
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 255, 255, 0), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());

			break;
		}
		else if (Engine->DeathParty)
		{
			if (sType == 1)
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 254, 128, 254), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());
			else if (sType == 2)
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 197, 209, 189), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());

			break;
		}
		else if (Engine->DeathMe)
		{
			if (sType == 1)
				Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 254, 128, 254), false, string_format("*** %s has defeated %s - ( %d, %d ) ***", kill.c_str(), Death.c_str(), X, Z).c_str());

			break;
		}

	}
	break;
	//case XSafeOpCodes::UPGRADE_RATE: 
	//	{
	//		uint32 Rate = pkt.read<uint32>();
	//		Engine->uiAnvil->SetResult("%" + std::to_string(Rate)); 
	//	}
	//	break;
	case XSafeOpCodes::CASTLE_SIEGE_TIMER:
		HandleCastleSiegeWarTimer(pkt);
		break;
	case XSafeOpCodes::ShowQuestList:
		Engine->uiSealToolTip->QuestCheck(pkt);
		break;
	case XSafeOpCodes::ACCOUNT_INFO_SAVE:
		Engine->HandleAccountInfoSave(pkt);
		break;
	case XSafeOpCodes::CHAOTIC_EXCHANGE:
		Engine->HandleChaoticExchange(pkt);
		break;
	case XSafeOpCodes::CHAT_LASTSEEN:
		Engine->HandleLastSeen(pkt);
		break;
	case XSafeOpCodes::AntiAfkList:
		Engine->RecvAntiAfkList(pkt);
		break;
	case XSafeOpCodes::WheelData:
		Engine->RecvWheelData(pkt);
		break;
	case XSafeOpCodes::TagInfo:
		Engine->HandleTagName(pkt);
		break;
	case XSafeOpCodes::PusRefund:
		Engine->HandlePusRefund(pkt);
		break;
	case XSafeOpCodes::QuestBoard:
	{
		pkt.SByte();

		std::string questName;
		uint16 Total, Cur;
		uint16 MonsterID;
		pkt >> questName >> Cur >> Total >> MonsterID;

		Engine->uiQuestComplated->SendQuestBoard(questName, Cur, Total, MonsterID, 1);
	}
	break;
	case XSafeOpCodes::MerchantEye:
	{
		uint16 bSize, sSocketID;
		pkt >> bSize;

		pkt.SByte();

		Engine->MerchantEyeLock.lock();
		Engine->MerchantEyeData.clear();
		for (int i = 0; i < bSize; i++)
		{

			pkt >> sSocketID;
			MerchantEyeData item;
			item.nIndex = 1;

			for (int a = 0; a < 12; a++)
			{
				std::string ItemName;
				pkt >> ItemName;

				item.strMerchantItem[a] = ItemName;

			}
			Engine->MerchantEyeData.insert(std::pair<uint16, MerchantEyeData>(sSocketID, item));
		}
		Engine->MerchantEyeLock.unlock();
		if (Engine->m_UiMgr->uiMerchantEye == NULL)
		{
			std::string uifName = Engine->dcpUIF(xorstr("BuhuR\\re_merchant_eye.bbuhurr")); // UYARI GİDERİLDİ
			Engine->m_UiMgr->uiMerchantEye = new CUIMerchantEye();
			Engine->m_UiMgr->uiMerchantEye->Init(Engine->m_UiMgr);
			Engine->m_UiMgr->uiMerchantEye->LoadFromFile(Engine->m_BasePath + uifName.c_str(), N3FORMAT_VER_1068); // Değişken güncellendi
			Engine->m_UiMgr->AddChild(Engine->m_UiMgr->uiMerchantEye);
			Engine->m_UiMgr->uiMerchantEye->Close();
			remove(uifName.c_str()); // Değişken güncellendi
		}
		Engine->m_UiMgr->uiMerchantEye->Open();
	}break;
	case XSafeOpCodes::GenieInfo:
	{
		uint8 Status;

		pkt >> Status;

		if (Status)
		{
			Engine->m_isGenieStatus = true;

			std::map<uint32, CSpell>::iterator itr;
			const vector<uint32> healSkills = {
				// Karus
				111001,111005,111500,111509,111518,111527,111536,111545,112560,112554,112557,
				111554,111557,111560,112001,112005,112500,112509,112518,112527,112536,112545,

				//El Morad
				211001,211005,211500,211509,211518,211527,211536,211545,211554,211557,212557,
				211560,212001,212005,212500,212509,212518,212527,212536,212545,212554,212560,

			};
			const vector<uint32> NovaSkills = {
				110571,210571,110671,210671,110771,210771,110560,210560,110660,210660,110760,210760,110545,210545,110645,210645,110745,210745,

			};

			const vector<uint32> ThirtyThreeSkills = {
				109533,
				209533,
				110533,
				210533,
				109633,
				209633,
				110633,
				210633,
				109733,
				209733,
				110733,
				210733,
			};

			const vector<uint32> buffskills = {
				111654,112654,211654,212654,111606,112606,211606,212606,212672,112673,212673,
				111603,112603,211603,212603,111612,112612,211612,212612,112671,212671,112672,
				111621,112621,211621,212621,111630,112630,211630,212630,112670,212670,211660,
				111639,112639,211639,212639,111651,112651,212655,211651,212651,111660,112660,
				212660,112676,212676,112675,212675,112674,212674,111609,112609,211609,211627,
				212609,111615,112615,211615,212615,111624,112624,211624,212624,111627,112627,
				212627,111629,112629,211629,212629,111633,112633,211633,112657,211657,212657,
				212633,111636,112636,211636,212636,111642,112642,211642,211656,212656,111657,
				212642,111645,112645,211645,212645,111655,112655,211655,111656,112656,

			};


			bool cont = false;
			for (itr = Engine->skillmap.begin(); itr != Engine->skillmap.end(); itr++)
			{
				if (Engine->m_PlayerBase->GetClass() != itr->second.dwID / 1000)
					continue;
				if (itr->second.iCastTime < 1)
					continue;

				if (std::find(ThirtyThreeSkills.begin(), ThirtyThreeSkills.end(), itr->second.dwID) != ThirtyThreeSkills.end())
					continue;

				// UYARI GİDERİLDİ: Hesaplama sonucu açıkça int8'e dönüştürüldü.
				int8 hesaps = (int8)(itr->second.iCastTime / 2);
				if (hesaps > 6)
					hesaps = 6;
				if (hesaps > 0)
					itr->second.iCastTime = hesaps;
				cont = false;//nxwile genie nova atmama sorunu
				if (std::find(NovaSkills.begin(), NovaSkills.end(), itr->second.dwID) != NovaSkills.end())
					continue;
				if (std::find(healSkills.begin(), healSkills.end(), itr->second.dwID) != healSkills.end())
					continue;
				if (std::find(buffskills.begin(), buffskills.end(), itr->second.dwID) != buffskills.end())
					continue;

				if (CSpell* spell = GetSkillBase(itr->second.dwID))
				{
					if (hesaps > 0)
						spell->iCastTime = hesaps;

				}
			}

		}
		else if (!Status)
		{
			Engine->m_isGenieStatus = false;
			std::map<uint32, CSpell>::iterator itr;

			for (itr = Engine->skillmap.begin(); itr != Engine->skillmap.end(); itr++)
			{
				auto bkp = Engine->skillmapBackup.find(itr->second.dwID);
				if (bkp == Engine->skillmapBackup.end())
					continue;

				itr->second.iCastTime = bkp->second.iCastTime;

				if (CSpell* spell = GetSkillBase(itr->second.dwID))
				{
					spell->iCastTime = bkp->second.iCastTime;

				}

			}

		}
	}
	break;
	default:
		break;
	}
}

void PearlEngine::HandlePusRefund(Packet & pkt) {
	uint8 opcode = pkt.read<uint8>();
	switch ((pusrefunopcode)opcode)
	{
	case pusrefunopcode::listsend:
	{
		if (PusRefundINIT) return;
		PusRefundINIT = true;

		vector<PUSREFUNDITEM> PusRefundItems;

		uint16 count = 0;
		pkt >> count;

		for (int i = 0; i < count; i++) {
			uint64 serial; uint32 sItemID, sPrice, expiredtime;
			pkt >> serial >> sItemID >> sPrice >> expiredtime;
			PusRefundItems.push_back(PUSREFUNDITEM(serial, sItemID, sPrice, expiredtime));
		}
		PusRefundINIT = true;
		Engine->m_UiMgr->pusrefund_itemlist = PusRefundItems;
	}
	break;
	case pusrefunopcode::itemnotfound:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : Item not found.")).c_str(), 0xa30000);
		break;
	case pusrefunopcode::timeexpired:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : The item you want to return has expired.")).c_str(), 0xa30000);
		break;
	case pusrefunopcode::procestime:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : Please wait at least 5 seconds for the return process.")).c_str(), 0xa30000);
		break;
	case pusrefunopcode::notinventory:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : The item was not found in their inventories.")).c_str(), 0xa30000);
		break;
	case pusrefunopcode::itemused:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : Used items cannot be returned.")).c_str(), 0xa30000);
		break;
	case pusrefunopcode::itemreurnsucces:
	{
		uint64 serial; uint32 itemid;
		pkt >> serial >> itemid;
		for (auto it = m_UiMgr->pusrefund_itemlist.begin(); it != m_UiMgr->pusrefund_itemlist.end(); ++it) {
			if (it->serial == serial && it->itemid == itemid) { m_UiMgr->pusrefund_itemlist.erase(it); break; }
		}
		Engine->uiPowerUpStore->UpdateRefundItemList(Engine->m_UiMgr->pusrefund_itemlist);
		Engine->uiPowerUpStore->RefundSetItems();
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("Power Up Store : The item has been successfully returned.")).c_str(), 0xa30000);
	}
	break;
	case pusrefunopcode::listadd:
	{
		uint64 serial; uint32 itemid, itemprice, expiredtime; uint16 itemcount, itemduration;
		pkt >> serial >> itemid >> itemcount >> itemprice >> itemduration >> expiredtime;
		if (!serial) return;
		m_UiMgr->pusrefund_itemlist.push_back(PUSREFUNDITEM(serial, itemid, itemprice, expiredtime));
		Engine->uiPowerUpStore->UpdateRefundItemList(Engine->m_UiMgr->pusrefund_itemlist);
		Engine->uiPowerUpStore->RefundSetItems(true);
	}
	break;
	}
}

void PearlEngine::addnewtagid(uint16 id, tagName tag) {
	tagLock.lock();
	auto itr = tagList.find(id);
	if (itr != tagList.end()) itr->second = tag;
	else tagList.insert({ id, tag });
	tagLock.unlock();
}

void PearlEngine::HandleTagName(Packet & pkt) {
	uint8 subcode = pkt.read<uint8>();
	switch ((tagerror)subcode)
	{
	case tagerror::Open:
	{
		if (!m_UiMgr) return;

		if (!Engine->uiTagChange) Engine->uiTagChange->OpenTagChange();
		if (!Engine->uiTagChange) return;

		Engine->SetVisible(Engine->uiTagChange->m_dVTableAddr, true);
	}
	break;
	case tagerror::List:
	{
		uint16 counter = 0;
		pkt >> counter;
		for (uint16 i = 0; i < counter; i++) {
			tagName tag;
			uint16 id = 0;
			pkt.DByte();
			pkt >> id >> tag.tag >> tag.r >> tag.g >> tag.b;
			addnewtagid(id, tag);
		}
	}
	break;
	case tagerror::success:
	{
		tagName tag;
		uint8 regipnu = 0; uint16 sockid;
		pkt.DByte();
		pkt >> regipnu >> sockid >> tag.tag >> tag.r >> tag.g >> tag.b;
		if (!regipnu) Engine->WriteInfoMessageExt((char*)string_format(xorstr("tag change success!")).c_str(), 0xa30000);
		addnewtagid(sockid, tag);
	}
	break;
	case tagerror::error:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("tag change error!")).c_str(), 0xa30000);
		break;
	case tagerror::already:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("tag change already!")).c_str(), 0xa30000);
		break;
	case tagerror::noitem:
		Engine->WriteInfoMessageExt((char*)string_format(xorstr("tag change no item!")).c_str(), 0xa30000);
		break;
	}
}

void PearlEngine::RecvAntiAfkList(Packet & pkt) {
	//antiAFKProto.clear();
	//uint16 size = 0; pkt >> size;
	//if (!size) return;
	//for (int i = 0; i < size; i++) {
	//	uint16 NpcID;
	//	pkt >> NpcID;
	//	if (!NpcID) continue;
	//	antiAFKProto.push_back(NpcID);
	//}

	uint8 oppcode = 0;
	uint16 size = 0;
	pkt >> oppcode;
	//printf("RecvAntiAfkList oppcode: %d \n", oppcode);
	if (oppcode == 1)
	{
		antiAFKProto.clear();
		pkt >> size;
		if (!size) return;
		for (int i = 0; i < size; i++) {
			uint16 NpcID;
			pkt >> NpcID;
			if (!NpcID)
				continue;
			//printf("SendAntiAfkList NpcID: %d \n", NpcID);
			antiAFKProto.push_back(NpcID);
		}
	}
	else if (oppcode == 4)
	{
		uint8 randomid;
		uint8 randomid2 = 0;
		pkt >> size;


		//for (int i = 0; i < 20; ++i) {
		//	CrRandomItem[i] = std::vector<uint16_t>(1, 0); // Her bir vektörü bir adet 0 ile baslat
		//}


		if (!size)
			return;

		//printf("CrRandomItem size: %d \n", size);

		for (int i = 0; i < 9999; ++i) {
			Engine->CrRandomItem[i].clear();
		}

		for (int i = 0; i < size; i++) {
			uint32 NpcID;
			pkt >> randomid >> NpcID;
			if (randomid && randomid != randomid2)
			{
				randomid2 = randomid;
				//Engine->CrRandomItem[randomid].clear();
			}

			if (!NpcID)
				continue;

			//printf("CrRandomItem[%d] - ItemID: %d \n", randomid, NpcID);
			Engine->CrRandomItem[randomid].push_back(NpcID);
		}
	}
}
void PearlEngine::RecvWheelData(Packet & pkt) {
	WheelItemData.clear();
	uint16 size = 0; pkt >> size;
	uint8 sCounter = 0;
	if (!size) return;
	for (int i = 0; i < size; i++) {
		if (sCounter >= 15)
			break;
		uint32 nItemID;
		pkt >> nItemID;
		if (!nItemID) continue;

		Engine->WheelItemData.insert(std::pair<uint8, uint32>(sCounter, nItemID));
		sCounter++;
	}
}
void PearlEngine::HandleLastSeen(Packet & pkt)
{
	std::string pTUser = "";
	pkt >> pTUser;
	if (pTUser.empty() || pTUser == "")
		return;

	uint8 UserLastSeen[2];
	pkt >> UserLastSeen[0] >> UserLastSeen[1];

	_PM_MAP* pPmMap = Engine->pmusers.GetData(pTUser);
	if (pPmMap == nullptr)
		return;

	pPmMap->LastSeen[0] = UserLastSeen[0];
	pPmMap->LastSeen[1] = UserLastSeen[1];
	pPmMap->LastSeenCheck = true;

}
void PearlEngine::HandleChaoticExchange(Packet & pkt)
{
	enum class ChaoticExchangeResult
	{
		ChaoticStop = 1,
		ChaoticSucces = 2
	};

	uint8 opcode;
	pkt >> opcode;

	switch ((ChaoticExchangeResult)opcode)
	{
	case ChaoticExchangeResult::ChaoticStop:
		ChaoticExchangeStop();
		break;
	case ChaoticExchangeResult::ChaoticSucces:
		ChaoticExchangeSucces();
		break;
	default:
		break;
	}
}

void PearlEngine::ChaoticExchangeStop()
{
	//Engine->uiPieceChangePlug->gemcount = 0;
}

void PearlEngine::ChaoticExchangeSucces()
{
	POINT pt;
	Engine->GetUiPos(Engine->uiPieceChangePlug->m_btnStop, pt);
	pt.y -= 2;
	Engine->m_UiMgr->SendMouseProc(UI_MOUSE_LBCLICK, pt, pt);
}

void HandleEventProcess(Packet& pkt)

{

	uint8 subcode = pkt.read<uint8>();



	if (subcode == TempleOpCodes::TEMPLE_EVENT)

	{

		uint16 active_event = 0, rem_time = 0;

		pkt >> active_event >> rem_time;

		if ((EventOpCode)active_event == EventOpCode::TEMPLE_EVENT_JURAD_MOUNTAIN

			&& rem_time > 0)

			Engine->OpenjuraidScreen(false, 0, 0, rem_time);

	}

	else if (subcode == TempleOpCodes::TEMPLE_EVENT_JOIN)

	{

		uint8 unk1;

		int16 active_event;

		pkt >> unk1 >> active_event;

		if (unk1 != 1 || (EventOpCode)active_event != EventOpCode::TEMPLE_EVENT_JURAD_MOUNTAIN)

			return;



		if (!Engine->m_UiMgr->uiJuraid)

			return;



		Engine->m_UiMgr->uiJuraid->JoinOrDisband(true);

	}

	else if (subcode == TempleOpCodes::TEMPLE_EVENT_DISBAND)

	{

		uint8 unk1;

		int16 active_event;

		pkt >> unk1 >> active_event;

		if (unk1 != 1 || (EventOpCode)active_event != EventOpCode::TEMPLE_EVENT_JURAD_MOUNTAIN)

			return;



		if (!Engine->m_UiMgr->uiJuraid)

			return;



		Engine->m_UiMgr->uiJuraid->JoinOrDisband(false);

	}

}

bool first = true;

bool __cdecl HandlePacket(Packet pkt)

{

	uint8 OpCode = pkt.GetOpcode();



	// --- NOVA VE ALAN BÜYÜSÜ FPS KORUMASI ---

	// Sunucudan (Incoming) gelen büyü paketlerini filtreleyerek, 

	// kalabalıkta aynı anda 50 efektin/hasar yazısının çizilmesini engelliyoruz.

	if (OpCode == WIZ_MAGIC_PROCESS)

	{

		Packet tempPkt = pkt; // Asıl paketin okunma imlecini bozmamak için kopyasını alıyoruz

		uint8 subCode;

		uint32 skillID;



		// Paketin içinden SubCode ve SkillID'yi okuyoruz

		tempPkt >> subCode >> skillID;



		// 3 = MAGIC_EFFECTING (Büyünün hedefe vurup hasar yazısı/efekt çıkardığı an)

		if (subCode == 3)

		{

			static uint32 lastSkillID = 0;

			static ULONGLONG lastTime = 0; // UYARI GİDERİLDİ: DWORD yerine ULONGLONG

			static int aoeCount = 0;

			ULONGLONG currentTime = GetTickCount64(); // UYARI GİDERİLDİ: GetTickCount64 yapıldı



			// Aynı skill 150 milisaniye içinde tekrar geliyorsa bu bir Alan Büyüsüdür (AOE)

			if (skillID == lastSkillID && (currentTime - lastTime) < 150)

			{

				aoeCount++;

				// İlk 2 hedefe efekti ve hasar yazısını çiz (vurduğunu görmek için),

				// 3. ve sonrasındaki hedeflerin paketlerini YUT! Oyun motoru bu paketleri HİÇ GÖRMEYECEK.

				if (aoeCount > 2)

				{

					return true; // Paketi bloklar ve işlemciyi overdraw (aşırı çizim) krizinden kurtarır!

				}

			}

			else

			{

				lastSkillID = skillID;

				lastTime = currentTime;

				aoeCount = 1;

			}

		}

	}

	// ----------------------------------------

	// ----------------------------------------



	switch (OpCode)

	{

	case WIZ_NOTICE_SEND:

	{

		std::string msg;

		pkt >> msg;

		if (first)

		{

			first = false;

			Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 254, 128, 254), false, msg.c_str());



		}

	}

	break;

	case XSafe:// E9 D5 true fals

	{

		XSafeHandlePacket(pkt);

		return true;

	}

	break;

	case WIZ_EVENT:

		HandleEventProcess(pkt);

		break;

	case WIZ_ADD_MSG:

	{

		uint8 opcode;

		pkt >> opcode;



		Engine->uiNoticeWind->MoticeMsgProcess(pkt, opcode);

		return true;

	}

	break;

	case WIZ_KILLASSIST:

	{

		// --- 1. OPTİMİZASYON: Disk I/O ve Ayarları Önbelleğe Alma ---

		// Option.ini'den okuma işlemleri maliyetlidir. Her paket geldiğinde değil, 

		// sistemi yormamak için en fazla 2 saniyede bir kontrol ediyoruz.

		static ULONGLONG lastConfigCheck = 0; // UYARI GİDERİLDİ: DWORD yerine ULONGLONG

		static int isSpecialSoundActive = 1;

		static int effectVolume = 100;

		static char basePath[MAX_PATH] = { 0 };



		ULONGLONG currentTime = GetTickCount64(); // UYARI GİDERİLDİ: GetTickCount64 kullanıldı



		if (currentTime - lastConfigCheck > 2000) // 2000 ms (2 Saniye) Cache süresi

		{

			isSpecialSoundActive = GetPrivateProfileIntA("Sound", "Effect", 1, "./Option.ini");

			effectVolume = GetPrivateProfileIntA("Sound", "EffectVolume", 100, "./Option.ini");



			// Ana dizin yolunu sadece program ilk çalıştığında 1 kez alıyoruz

			if (basePath[0] == '\0')

			{

				GetModuleFileNameA(NULL, basePath, MAX_PATH);

				char* lastSlash = strrchr(basePath, '\\');

				if (lastSlash) *lastSlash = '\0';

			}



			lastConfigCheck = currentTime;

		}



		// Ayarlar kapalıysa veya ses yoksa direkt çık

		if (isSpecialSoundActive == 0 || effectVolume <= 0) break;



		// --- Mevcut Paket Okuma İşlemleri ---

		uint8 typeCode = pkt.read<uint8>();

		pkt.read<uint8>();

		pkt.read<uint32>();

		std::string killerName;

		pkt >> killerName;

		pkt.read<uint8>();

		uint16 killCount = pkt.read<uint16>();



		DWORD pChar = *(DWORD*)KO_PTR_CHR;

		if (pChar == 0) break;



		// Irk ve Cinsiyet Kontrolü

		uint8 raceID = SafeReadMemoryByte(pChar + 0x55C);

		bool isFemale = (raceID == 13);



		int randomVoice = (currentTime % 4) + 1; // GetTickCount() yerine hazır alınmış değişkeni kullandık

		char genderFolder[10];

		sprintf_s(genderFolder, "%s%d", isFemale ? "f" : "m", randomVoice);

		std::string typeFolder = (typeCode == 1) ? "kill" : "asist";



		int fileNumber = killCount;

		if (killCount >= 13) {

			fileNumber = ((killCount - 13) % 3) + 10;

		}



		char finalPath[MAX_PATH];

		sprintf_s(finalPath, "%s\\Snd\\%s\\%s\\%02d.wav", basePath, typeFolder.c_str(), genderFolder, fileNumber);



		// --- 2. OPTİMİZASYON: Gereksiz Sistem Çağrılarını Filtreleme ---

		DWORD dwAttrib = GetFileAttributesA(finalPath);

		if (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))

		{

			// Ses seviyesini her kill'de sisteme dayatmak yerine, sadece ini dosyasındaki

			// değer değiştiğinde waveOutSetVolume fonksiyonunu çağırıyoruz.

			static DWORD lastSetVolume = 0xFFFFFFFF;

			DWORD winVolume = (effectVolume * 0xFFFF) / 100;

			DWORD finalVolume = (winVolume & 0xFFFF) | (winVolume << 16);



			if (lastSetVolume != finalVolume) {

				waveOutSetVolume(NULL, finalVolume);

				lastSetVolume = finalVolume;

			}



			// Ses oynatma - Asenkron olduğu için bir önceki sesi kesip anında yenisini başlatır. 

			// Disk I/O temizlendiği için FPS drop yaşatmaz.

			PlaySoundA(finalPath, NULL, SND_ASYNC | SND_FILENAME | SND_NODEFAULT);

		}

	} break;

	case WIZ_CHAT:

	{

		uint8 type, nation;

		pkt >> type >> nation;

		if (type == 2)

		{

			int16 sID;

			string user, msg;

			uint8 auth = 0;

			int8 rank;

			pkt >> sID;

			pkt.SByte();

			pkt >> user;

			pkt.DByte();

			pkt >> msg >> rank >> auth;



			if (user.empty() || msg.empty()/* || auth > 0*/) //Renkli Pm için authority kontrolü kapatildi 27.09.2020

				return false;



			_PM_MAP* pPmMap = Engine->pmusers.GetData(user);

			if (pPmMap == nullptr)

			{

				_PM_MAP* pPmMap2 = new _PM_MAP;

				pPmMap2->sID = sID;

				pPmMap2->uName = user;

				pPmMap2->msgcount = 1;

				pPmMap2->btype = auth;

				pPmMap2->MessageCountCheck = true;

				pPmMap2->MessageClean = true;



				Engine->pmusers.PutData(user, pPmMap2);

			}





		}

	}

	break;

	case WIZ_CHAT_TARGET:

	{

		uint8 type;

		pkt >> type;

		if (type == 1)

		{

			uint8 auth = 0; int8 rank;

			int16 tmp;

			string user;

			pkt >> tmp >> user >> rank >> auth;

			if (tmp == 1)

			{

				if (user.empty()/* || auth > 0*/) //Renkli Pm için authority kontrolü kapatildi 27.09.2020

					return false;



				_PM_MAP* pPmMap = Engine->pmusers.GetData(user);

				if (pPmMap == nullptr)

				{

					_PM_MAP* pPmMap = new _PM_MAP;

					pPmMap->uName = user;

					pPmMap->msgcount = 0;

					pPmMap->btype = auth;

					pPmMap->MessageCountCheck = true;

					pPmMap->MessageClean = false;

					Engine->pmusers.PutData(user, pPmMap);

				}

			}

		}

	}

	break;

	case WIZ_CLASS_CHANGE:

	{

		uint8 SubOpCode = 0, ReturnValue = 0;

		pkt >> SubOpCode >> ReturnValue;



		if (SubOpCode == 3 && ReturnValue == 1)

		{

			uint32 gold;

			uint16 str, hp, dex, intx, mp;

			int16 maxhp, maxmp;

			uint16 totalhit;

			uint32 maxweight;

			int16 points;



			pkt >> gold >> str >> hp >> dex >> intx >> mp >> maxhp >> maxmp >> totalhit >> maxweight >> points;

			if (Engine->uiHPBarPlug != NULL)

			{

				Engine->uiHPBarPlug->HPChange(maxhp, maxhp);

				Engine->uiHPBarPlug->MPChange(maxmp, maxmp);

			}

		}

	}

	break;

	case WIZ_POINT_CHANGE:

	{

		uint8 subcode;

		pkt >> subcode;





		uint32 tmp32;

		uint16 maxhp, hp, maxmp, mp, tmp;

		pkt >> tmp >> maxhp >> maxmp >> tmp >> tmp32 >> hp >> mp;

		if (Engine->uiHPBarPlug != NULL)

		{

			Engine->uiHPBarPlug->HPChange(hp, maxhp);

			Engine->uiHPBarPlug->MPChange(mp, maxmp);

		}

	}

	break;

	case WIZ_STATE_CHANGE:

	{

		uint8 bType; /*= pkt.read<uint8>(), buff;*/

		uint16 GetID;

		uint32 nBuff;/* = pkt.read<uint32>();

		buff = *(uint8 *)&nBuff; // don't ask*/

		pkt >> GetID >> bType >> nBuff;



	}

	break;

	case WIZ_LEVEL_CHANGE:

	{



		short maxhp, hp, maxmp, mp;

		uint16 sock;

		uint8 level, freeskill;

		int16 points;

		int64 maxexp, xp;

		pkt >> sock >> level >> points >> freeskill >> maxexp >> xp >> maxhp >> hp >> maxmp >> mp;



		if (Engine->GetSocketID() != sock)

			return false;



		if (Engine->uiHPBarPlug != NULL) {

			Engine->uiHPBarPlug->HPChange(hp, maxhp);

			if (Engine->dc) Engine->dc->Update(true);



			Engine->uiHPBarPlug->MaxExp = maxexp;

			Engine->uiHPBarPlug->ExpChange(xp, maxexp);

		}

	}

	break;

	case WIZ_EXP_CHANGE:

	{

		uint8 opcode;

		pkt >> opcode;

#if (HOOK_SOURCE_VERSION == 1098)

		if (opcode == 1 && Engine->uiHPBarPlug != NULL) {

			int64 exp;

			pkt >> exp;

			Engine->uiHPBarPlug->ExpChange(exp, Engine->uiHPBarPlug->MaxExp);

		}

#else

		/*if (opcode == 3 && Engine->uiHPBarPlug != NULL) {

		pkt >> Engine->Player.burninglevel;

		if (Engine->Player.burninglevel > 3)

		Engine->Player.burninglevel = 3;



		Engine->uiHPBarPlug->BurningChange(Engine->Player.burninglevel);

		}*/

#endif

	}

	break;

	case WIZ_HP_CHANGE:

	{

		int32_t maxhp, hp; // Veriyi 32-bit olarak okuyarak taşmaları (overflow) engelliyoruz

		uint32_t tid;      // Pakette gelen target ID bilgisini de çekerek paket yapısını tam karşılıyoruz 



		pkt >> maxhp >> hp >> tid;



		if (Engine->uiHPBarPlug != NULL)

		{

			// Gelen değerlerin negatif olmamasını garanti altına alıyoruz

			if (hp < 0) hp = 0;

			if (hp > maxhp) hp = maxhp;



			Engine->uiHPBarPlug->HPChange((short)hp, (short)maxhp);

		}

	}

	break;

	case WIZ_MSP_CHANGE:

	{

		short maxmp, mp;

		pkt >> maxmp >> mp;

		if (Engine->uiHPBarPlug != NULL)

			Engine->uiHPBarPlug->MPChange(mp, maxmp);

	}

	break;

	case WIZ_SEL_CHAR:

		Engine->m_bSelectedCharacter = true;

		break;

	case WIZ_MYINFO:

	{

		Engine->m_bSelectedCharacter = true;

		Engine->m_bGameStart = true;

		SendHWID();



		if (Engine->uiSeedHelperPlug)

			Engine->uiSeedHelperPlug->SendOption();

	}

	break;

	case 0xFA: // --- WIZ_CUSTOM_1V1_UI (SKOR FIXLENDİ) ---

	{

		uint8 subOp = pkt.read<uint8>();



		if (subOp == 1) { // VS Başladı (Panel Aç)

			g_i1v1TimeLeft = pkt.read<uint16>();

			pkt >> g_str1v1Player1 >> g_str1v1Player2;

			g_i1v1KillsP1 = pkt.read<uint8>();   // Karus Başlangıç Skor (0)

			g_i1v1KillsP2 = pkt.read<uint8>();   // Elmo Başlangıç Skor (0)

			g_i1v1MaxScore = pkt.read<uint8>();  // Hedef Skor (7)

			g_bIs1v1Active = true;

			g_dw1v1LastTick = GetTickCount64(); // UYARI GİDERİLDİ: GetTickCount64 yapıldı.

		}

		else if (subOp == 2) { // VS Bitti

			g_bIs1v1Active = false;

			g_bShowResultText = false;

		}

		else if (subOp == 4) { // Kill Sonrası Skor Güncelleme (BURASI ÖNEMLİ)

			g_i1v1KillsP1 = pkt.read<uint8>();  // Karus Skor

			g_i1v1KillsP2 = pkt.read<uint8>();  // El Morad Skor

			g_i1v1MaxScore = pkt.read<uint8>(); // Hedef Skor

		}

		return true;

	}break;

	case WIZ_PREMIUM:

	{

		uint8 subcode;

		pkt >> subcode;

		if (subcode == 2)

		{

			uint8 PremiumStatus;

			uint32 sPremiumDay;

			pkt >> PremiumStatus >> sPremiumDay;



			if (Engine->uiClanWindowPlug != NULL)

			{

				Engine->SetStringColor(Engine->uiClanWindowPlug->ClanPremStatus, D3DCOLOR_ARGB(255, 0, 254, 0));

				Engine->SetString(Engine->uiClanWindowPlug->ClanPremStatus, "Active");

			}

		}

		else

		{

			if (Engine->uiClanWindowPlug != NULL)

			{

				Engine->SetStringColor(Engine->uiClanWindowPlug->ClanPremStatus, D3DCOLOR_ARGB(255, 255, 0, 0));

				Engine->SetString(Engine->uiClanWindowPlug->ClanPremStatus, "DeActive");

			}

		}

	}

	break;
#if (HOOK_SOURCE_VERSION == 1098)
	case WIZ_PARTY:
	{
		uint8 subcode;
		pkt >> subcode;
		if (subcode == PARTY_INSERT)
		{
			short partyid, maxhp, hp, maxmp, mp;
			uint8 ret, level, nation, UserPartyType;
			uint16 iclass;
			string userName;
			//pkt >> ret >> userName >> maxhp >> hp >> level >> iclass >> maxmp >> mp >> nation;
			pkt >> partyid >> ret >> userName >> maxhp >> hp >> level >> iclass >> maxmp >> mp >> nation >> UserPartyType;
			Engine->m_bInParty = true;
#if (HOOK_SOURCE_VERSION == 1098)
			if (Engine->m_bInParty == true)
			{
				if (Engine->uiTaskbarMain != NULL)
				{
					Engine->SetVisible(Engine->uiTaskbarMain->m_btninvite, false);
					Engine->SetState(Engine->uiTaskbarMain->m_btninvite, UI_STATE_BUTTON_DOWN);
					Engine->SetVisible(Engine->uiTaskbarMain->m_btndisband, true);
					Engine->SetState(Engine->uiTaskbarMain->m_btndisband, UI_STATE_BUTTON_NORMAL);
				}
			}

#else

			if (Engine->uiTaskbarMain != NULL) {
				Engine->SetState(Engine->uiTaskbarMain->m_btnPartySettings, UI_STATE_BUTTON_NORMAL);
			}
#endif

		}
		else if (subcode == PARTY_DELETE)
		{
			Engine->m_bInParty = false;
#if (HOOK_SOURCE_VERSION == 1098)	
			if (Engine->m_bInParty == false)
			{
				if (Engine->uiTaskbarMain != NULL)
				{
					Engine->SetVisible(Engine->uiTaskbarMain->m_btninvite, true);
					Engine->SetState(Engine->uiTaskbarMain->m_btninvite, UI_STATE_BUTTON_NORMAL);
					Engine->SetVisible(Engine->uiTaskbarMain->m_btndisband, false);
					Engine->SetState(Engine->uiTaskbarMain->m_btndisband, UI_STATE_BUTTON_DOWN);
				}
			}
#else
			if (Engine->uiTaskbarMain != NULL) {
				Engine->SetState(Engine->uiTaskbarMain->m_btnPartySettings, UI_STATE_BUTTON_DISABLE);
			}
#endif
		}
	}
	break;
#endif
	case WIZ_ZONE_CHANGE:
		Engine->HandleZoneChange(pkt);
		break;
	case WIZ_TARGET_HP:
	{
		if (!Engine->m_bHookStart) {
			StartHook();
		}
		if (Engine->uiTargetBar != NULL)
			Engine->uiTargetBar->SetTargetHp(pkt);
	}
	break;
	case WIZ_GAMESTART:
	{
		Engine->HandleGameStart(pkt);
		ASMPatch((DWORD)0x00556689, (char*)"\xEB\x37", 2);
	}
	break;
	case WIZ_GENIE:
	{
		uint8 command;
		uint16 GenieTime;
		pkt >> command >> GenieTime;
#if 0
		std::string logla = string_format("command %d - GenieTime %d\n", command, GenieTime);
		printf("%s\n", logla.c_str());
		Engine->WriteChatAddInfo(D3DCOLOR_ARGB(255, 197, 209, 189), false, logla.c_str());
#endif
		if (GenieTime == 0)
			Engine->Genie1TimeCheck = false;
	}
	break;
	case WIZ_ITEM_MOVE:
	{
		if (!Engine->m_bHookStart)
			StartHook();

		uint8 command, subcommand, x1, x2;
		uint16 m_sTotalHit, m_sTotalAc;
		uint32 m_sMaxWeight;
		short m_MaxHp, m_MaxMp;
		int16 BonusTotal[5];

		uint16 m_sFireR, m_sColdR, m_sLightningR;
		uint16 m_sMagicR, m_sDiseaseR, m_sPoisonR;

		int16 hp, mp;
		uint32 cash, moneyreq;
		uint16 dd, axe, sword, mace, spear, bow, jamadar;

		pkt >> command >> subcommand;

		if (subcommand != 0 && command != 2)
		{
			pkt >> m_sTotalHit >> m_sTotalAc >> m_sMaxWeight >> x1 >> x2 >> m_MaxHp >> m_MaxMp;
			for (int z = 0; z < 5; z++)
				pkt >> BonusTotal[z];

			pkt >> m_sFireR >> m_sColdR >> m_sLightningR >> m_sMagicR >> m_sDiseaseR >> m_sPoisonR;
			pkt >> cash >> dd >> axe >> sword >> mace >> spear >> bow >> jamadar >> moneyreq >> hp >> mp;

			Engine->Player.KnightCash = cash;
			Engine->Player.moneyreq = moneyreq;

			if (Engine->uiState != NULL)
			{
				Engine->uiState->m_iCash = cash;
				Engine->uiState->m_iDagger = dd;
				Engine->uiState->m_iAxe = axe;
				Engine->uiState->m_iSword = sword;
				Engine->uiState->m_iClub = mace;
				Engine->uiState->m_iSpear = spear;
				Engine->uiState->m_iArrow = bow;
				Engine->uiState->m_iJamadar = jamadar;
				Engine->uiState->UpdateUI();
			}

			if (Engine->uiTradeInventory != NULL)
				Engine->uiTradeInventory->UpdateTotal(cash);

			if (Engine->uiHPBarPlug != NULL)
			{
				Engine->uiHPBarPlug->HPChange(hp, m_MaxHp);
				Engine->uiHPBarPlug->MPChange(mp, m_MaxMp);
			}
			uiINIT = true;
		}
	}
	break;

	case WIZ_MERCHANT:
	{
		uint8 subCode;
		pkt >> subCode;

		if (Engine->m_MerchantMgr != NULL)
		{
			if (subCode == MERCHANT_ITEM_ADD)
				Engine->m_MerchantMgr->UpdateRecentItemAddReq(pkt);
			else if (subCode == MERCHANT_SLOT_UPDATE)
				Engine->m_MerchantMgr->UpdateItemDisplaySlots(pkt);
			else if (subCode == MERCHANT_ITEM_CANCEL)
				Engine->m_MerchantMgr->RemoveItemFromSlot(pkt);
			else if (subCode == MERCHANT_INSERT)
				Engine->m_MerchantMgr->MerchantCreated(pkt);
			else if (subCode == MERCHANT_ITEM_LIST)
				Engine->m_MerchantMgr->SetTheirMerchantSlots(pkt);
			else if (subCode == MERCHANT_TRADE_CANCEL)
				Engine->m_MerchantMgr->ResetMerchant();
			else if (subCode == MERCHANT_CLOSE)
				Engine->m_MerchantMgr->ResetMerchant();
		}
		switch (subCode)
		{
			
		case 0x32:
		{
			// UYARI GİDERİLDİ: Kullanılmayan 'b' değişkeni silindi.
			uint8_t a, MerchantState, isPremium;
			uint16_t mySocket;
			uint32_t nPrice;
			uint8_t isKC;

			pkt >> a
				>> mySocket
				>> MerchantState
				>> isPremium;
			//...

			Engine->merchantItemsPriceLock.lock();
			Engine->merchantItemsPrice.erase(mySocket);

			MerchantItemView item;
			// listCount hesaplamasi
			for (int i = 0, listCount = (MerchantState == 1 ? 4 : (isPremium ? 8 : 4)); i < listCount; i++)
			{
				pkt >> nPrice >> isKC; // Dogru sekilde kullaniliyor

				// UYARI GİDERİLDİ: int olan 'i' uint8_t türüne dönüştürüldü.
				item.bSrcPos[i] = (uint8_t)i;
				item.isKC[i] = isKC;
				item.price[i] = nPrice;
			}

			Engine->merchantItemsPrice.insert(std::pair<uint16_t, MerchantItemView>(mySocket, item)); // uint16 yerine uint16_t
			Engine->merchantItemsPriceLock.unlock();
		}
		break;
		break;
		}
	}
	break;
	//case WIZ_ITEM_UPGRADE:
	//	{
	//		uint8 subCode;
	//		pkt >> subCode;
	//		if (subCode == ITEM_BIFROST_EXCHANGE)
	//		{
	//			uint8 resultOpCode;
	//			pkt >> resultOpCode;

	//			if (resultOpCode == Failed) // kirdirmayi durdur
	//			{
	//				Engine->uiPieceChangePlug->m_bAutoExchangeStarted = false;
	//				Engine->uiPieceChangePlug->m_Timer = NULL;
	//			}
	//			else if (resultOpCode == Success)
	//			{
	//				POINT pt;
	//				Engine->GetUiPos(Engine->uiPieceChangePlug->m_btnStop, pt);
	//				pt.y -= 2;
	//				Engine->m_UiMgr->SendMouseProc(UI_MOUSE_LBCLICK, pt, pt);
	//			}
	//		}
	//	}
	//	break;
//		case WIZ_RANK:
//			Engine->Player.RankPacketReceived = true;
//			break;
//		case WIZ_PARTY_HP:
//		{
//			uint8 subCode;
//			pkt >> subCode;
//
//			if (subCode == 1 && Engine->uiPartyBBS != NULL)
//				Engine->uiPartyBBS->UpdatePartyUserHPBAR(pkt);
//		}
//			break;
	}

	if (!Engine->UPanelStart && Engine->m_bGameStart)
	{
		Packet result(XSafe);
		result << uint8_t(XSafeOpCodes::UIINFO);
		Engine->Send(&result);
		Engine->UPanelStart = true;
	}

	/*Engine->m_PlayerBase->UpdateGold();*/

	return false;
}

void PearlEngine::HandleAccountInfoSave(Packet & pkt)
{
	enum class AccountInfoSave { Open = 1, Close = 2 };

	uint8 Opcode;
	pkt >> Opcode;
	switch ((AccountInfoSave)Opcode)
	{
	case AccountInfoSave::Open:
	{
		if (m_UiMgr == NULL)
			return;

		if (Engine->uiAccountRegisterPlug == NULL)
		{
			Engine->uiAccountRegisterPlug = new CUIAccountRegister();
		}
		Engine->uiAccountRegisterPlug->Open();
	}
	break;
	case AccountInfoSave::Close:
	{
		uint8 Opcode;
		pkt >> Opcode;

		if (m_UiMgr == NULL
			|| Engine->uiAccountRegisterPlug == NULL)
			return;

		if (Opcode != 1) {
			Engine->uiAccountRegisterPlug->RefreshText();
			Engine->WriteInfoMessageExt((char*)string_format(xorstr("Account Info Save Failed")).c_str(), 0xa30000);
			return;
		}

		if (Engine->uiAccountRegisterPlug != NULL) {
			Engine->uiAccountRegisterPlug->Close();
		}
	}
	break;
	default:
		break;
	}
}
// UYARI GİDERİLDİ (C4100): 'pkt' başvurulmayan parametre yoruma alındı.
void PearlEngine::HandleGameStart(Packet& /*pkt*/)
{
	m_bSelectedCharacter = true;
	m_bGameStart = true;
	LoadingControl = false;
	gameStarted = true;
	if (Engine->dc) Engine->dc->Update(true);
}

void PearlEngine::HandleZoneChange(Packet& pkt)
{
	uint8 subCode;
	pkt >> subCode;

	if (Engine->dc) Engine->dc->Update(true);

	switch (subCode)
	{
	case 2:
		LoadingControl = false;
		Player.isTeleporting = false;
		break;
	case 3:
	{
		uint16 oldzone = Player.ZoneID;
		uint16 newZone;
		pkt >> newZone;
		// UYARI GİDERİLDİ: uint16 olan newZone, uint8'e dönüştürüldü.
		Player.ZoneID = (uint8)newZone;
		Player.isTeleporting = false;
		LoadingControl = false;

		if (uiQuestPage)
			uiQuestPage->InitQuests();

		if (Player.ZoneID != 30 && oldzone == 30 && Engine->m_UiMgr->uiCSW)
		{
			Engine->m_UiMgr->uiCSW->Close();
		}
	}
	break;
	}
}

std::mutex recv_mutex;

void RecvMake(RECV_DATA* pRecv)
{
	// Güvenlik: Paket boşsa veya hatalıysa işlemi iptal et
	if (!pRecv || pRecv->Size <= 0)
		return;

	Packet pkt;

	// Boyutu 1 eksilterek sadece veri kısmını alıyoruz
	unsigned int length = pRecv->Size - 1;

	pkt = Packet(pRecv->Data[0]); // OpCode

	if (length > 0)
	{
		pkt.resize(length);
		memcpy((void*)pkt.contents(), &pRecv->Data[1], length);
	}

	// Paket artık ana thread'i veya diğer paketleri kilitlemeden işlenecek
	HandlePacket(pkt);
}

// ----------------------------------------------------
// C3861 HATASININ ÇÖZÜMÜ: rdwordExt fonksiyonu burada tanımlanmalı
DWORD rdwordExt(DWORD ulBase)
{
	if (!IsBadReadPtr((VOID*)ulBase, sizeof(DWORD)))
	{
		return(*(DWORD*)(ulBase));
	}
	return 0;
}
// ----------------------------------------------------

typedef bool(__stdcall* tRecv)(RECV_DATA* pRecv, void* pParam);
tRecv oRecv; // Orijinal tanım bu şekildeydi
DWORD pktRet = 0;

// Orijinal hook fonksiyonundaki gereksiz if blokları temizlendi
bool WINAPI hkRECV(RECV_DATA* pRecv, void* pParam)
{
	if (!pRecv || pRecv->Size < 1)
		return true;

	pktRet = rdwordExt(KO_DLG);

	if (pktRet == 0)
		return true;

	__asm
	{
		MOV ECX, pktRet
		PUSH pParam
		PUSH pRecv
		CALL oRecv
	}

	RecvMake(pRecv);

	return true;
}

const DWORD KO_OPEN_PUS = 0x008C4CAA;

void __fastcall pusuAc()
{
	if (Engine->uiPowerUpStore == NULL)
	{
		Engine->uiPowerUpStore->OpenPowerUpStore();
	}
	Engine->uiPowerUpStore->UpdateItemList(Engine->m_UiMgr->item_list, Engine->m_UiMgr->cat_list);
	Engine->uiPowerUpStore->UpdateRefundItemList(Engine->m_UiMgr->pusrefund_itemlist);
	Engine->uiPowerUpStore->Open();
}

void __declspec(naked) hkOpenPUS()
{
	__asm {
		pushad
		pushfd
		call pusuAc
		popfd
		popad
		mov edx, KO_OPEN_PUS
		add edx, 9
		push edx
		ret
	}
}

bool RecvMake2(RECV_DATA* pRecv)
{
	RECV_DATA tmp = *pRecv;

	Packet pkt;

	unsigned int length = tmp.Size;
	if (length > 0)
		length--;

	pkt = Packet(tmp.Data[0]);
	if (length > 0)
	{
		pkt.resize(length);
		memcpy((void*)pkt.contents(), &tmp.Data[1], length);
	}
	if (pRecv->Size > 0)
	{
		if (pRecv->Data[0] == WIZ_WAREHOUSE)
			Engine->Player.m_iClanBank = false;

		if (pRecv->Data[0] == WIZ_CLANWAREHOUSE)
		{
			pRecv->Data[0] = WIZ_WAREHOUSE;

			if (!Engine->Player.m_iClanBank)
				Engine->Player.m_iClanBank = true;
		}
	}
	return HandlePacket(pkt);
}

DWORD recvReturnAddress = 0;

// --- YENİ EKLENEN: GELEN (INCOMING) NOVA/ALAN BÜYÜSÜ EFEKT SUSTURUCU ---
void __cdecl SanitizeIncomingPacket(RECV_DATA* pRecv)
{
	if (!pRecv || pRecv->Size < 6) return;

	uint8 opcode = pRecv->Data[0];
	if (opcode == WIZ_MAGIC_PROCESS)
	{
		uint32 skillID = *(uint32*)&pRecv->Data[2];
		static uint32 lastIncomingSkillID = 0;
		static clock_t lastIncomingSkillTime = 0;
		static int incomingSkillCount = 0;

		// Aynı skill son 250 ms içinde geliyorsa bu bir Alan Büyüsüdür (Nova vb.)
		if (skillID == lastIncomingSkillID && (clock() - lastIncomingSkillTime) < 250)
		{
			incomingSkillCount++;
			if (incomingSkillCount > 1)
			{
				// Efekt (FX) motorunu kandır: Oyun motoru 2. 3. 50. paketteki adamı hasar yemiş sayar
				// Fakat skill ID'si 0 olduğu için koca alev topunu adamın kafasına ÇİZMEZ!
				*(uint32*)&pRecv->Data[2] = 0;
			}
		}
		else
		{
			lastIncomingSkillID = skillID;
			lastIncomingSkillTime = clock();
			incomingSkillCount = 1;
		}
	}
}

// UYARI GİDERİLDİ (C4100): 'pParam' ASM içinde çağrıldığı için parametreden yoruma alındı.
void __declspec(naked) hkRecv_thyke(RECV_DATA* pRecv, void* /*pParam*/)
{
	__asm {
		push ebp
		mov ebp, esp
		push ebx
		push esi
		push edi
		pushad
		pushfd
		mov eax, [ebp + 4]
		mov recvReturnAddress, eax
		mov eax, dword ptr[pRecv]
		cmp dword ptr[eax + 4], 0
		je retback
		push eax
		call RecvMake2
		add esp, 4
		movzx ecx, al
		test ecx, ecx
		jne retend
		// devam et
		retback :
		popfd
			popad
			pop edi
			pop esi
			pop ebx
			pop ebp
			push - 1
			push 0x00B99486
			mov eax, 0x00572B20
			add eax, 7
			jmp eax
			// bitir
			retend :
		popfd
			popad
			pop edi
			pop esi
			pop ebx
			pop ebp
			mov al, 01
			add esp, 0x0c
			jmp recvReturnAddress
	}
}

void PearlEngine::InitRecvHook()
{
	DetourFunction((PBYTE)KO_OPEN_PUS, (PBYTE)hkOpenPUS);
	//oRecv = (tRecv)DetourFunction((PBYTE)KO_RECV_FUNC, (PBYTE)hkRECV);

	DetourFunction((PBYTE)0x00572B20, (PBYTE)hkRecv_thyke);
}

/* Connection Gain or Lose */
int WINAPI ConnectDetour(SOCKET s, const sockaddr* addr, int namelen)
{
	LogCapConnectDiscovery(addr);
	struct sockaddr_in* addr_in = (struct sockaddr_in*)addr;

	// --- XTREME GİZLİ PORT YÖNLENDİRMESİ EKLENDİ ---
	if (ntohs(addr_in->sin_port) == 15001)
	{
		addr_in->sin_port = htons(15572);
	}
	// -----------------------------------------------

	// Oyun sunucusu bağlantısını yakala (reconnect köprüsü için).
	if (ntohs(addr_in->sin_port) == 15572)
	{
		bridgeGameSocket = s;
		InterlockedExchange(&bridgeIntentionalClose, 0);
		InterlockedExchange(&reconnectTestDisconnecting, 0);
		InterlockedExchange(&reconnectHoldExpired, 0);
		if (IsBridgeActive())
			ReleaseReconnectBridge();
	}

#pragma warning(suppress : 4996)
	char* _s = inet_ntoa(addr_in->sin_addr);
	string hostAddress = string(_s);

	Engine->m_connectedIP = hostAddress;
#if XTREME_LISANS == 1
	if (!IsLicensed(hostAddress))
	{
		if (Engine->m_UiMgr != NULL)
			Engine->m_UiMgr->ShowMessageBox(xorstr("Baglanti Reddedildi"), xorstr("Sunucu ve Client arasinda Ip adresi uyumsuz."), MsgBoxTypes::Ok, PARENT_LOGIN);
		else
			Engine->Shutdown(xorstr("Baglanti Reddedildi Sunucu ve Client arasinda Ip adresi uyumsuz."));
		return WSAECONNREFUSED;
	}
#endif
	return OrigConnect(s, addr, namelen);
}

int WSAAPI WSAStartupDetour(WORD wVersionRequired, LPWSADATA lpWSAData)
{
	isAlive = true;
	return OrigWSAStartup(wVersionRequired, lpWSAData);
}

// UYARI GİDERİLDİ: 'name' parametresi, isim çakışmasını (C4459) önlemek için 'pName' olarak değiştirildi.
int WSAAPI WSAConnectDetour(SOCKET s, const sockaddr* pName, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS) {
	struct sockaddr_in* addr_in = (struct sockaddr_in*)pName;

	// --- XTREME GİZLİ PORT YÖNLENDİRMESİ EKLENDİ ---
	// Client 15001'e bağlanmaya çalışırsa, onu asıl dinlenen 15572 portuna yönlendir
	if (ntohs(addr_in->sin_port) == 15001)
	{
		addr_in->sin_port = htons(15572);
	}
	// -----------------------------------------------

	// Oyun sunucusu bağlantısını yakala (reconnect köprüsü için).
	if (ntohs(addr_in->sin_port) == 15572)
	{
		bridgeGameSocket = s;
		InterlockedExchange(&bridgeIntentionalClose, 0);
		if (IsBridgeActive())
			ReleaseReconnectBridge();
	}

#pragma warning(suppress : 4996)
	char* _s = inet_ntoa(addr_in->sin_addr);
	string hostAddress = string(_s);

	Engine->m_connectedIP = hostAddress;
#if XTREME_LISANS == 1
	if (!IsLicensed(hostAddress))
	{
		if (Engine->m_UiMgr != NULL)
			Engine->m_UiMgr->ShowMessageBox(xorstr("Baglanti Reddedildi"), xorstr("Sunucu ve Client arasinda Ip adresi uyumsuz."), MsgBoxTypes::Ok, PARENT_LOGIN);
		else
			Engine->Shutdown(xorstr("Baglanti Reddedildi Sunucu ve Client arasinda Ip adresi uyumsuz."));
		return WSAECONNREFUSED;
	}
#endif

	return OrigWSAConnect(s, pName, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS);
}

void PearlEngine::InitJmpHook(DWORD hookFuncAddr, DWORD myFuncAddr)
{
	SetMemArray(hookFuncAddr, 0x90, 6);
	JMPHOOK(hookFuncAddr, myFuncAddr);
}

inline void PearlEngine::JMPHOOK(DWORD Addr1, DWORD Addr2)
{
	BYTE jmp[] = { 0xE9,0,0,0,0 };
	DWORD diff = CalculateCallAddrWrite(Addr2, Addr1);

	memcpy(jmp + 1, &diff, 4);
	WriteProcessMemory(HANDLE(-1), (LPVOID)Addr1, jmp, 5, 0);
}
void SendHWID()
{
	isAlive = true;
	// UYARI GİDERİLDİ: Dizi başlatılırken {0} ile doldurularak C6054 (Null-terminate) hatası önlendi.
	char AccName[25] = { 0 };
	ReadProcessMemory(GetCurrentProcess(), (LPVOID)KO_ACC, AccName, sizeof(AccName), NULL);
	string m_strAccountID = string(AccName);
	uint16 MACData1, MACData2 = 0;
	GetMacHash(MACData1, MACData2);
	int64 UserHardwareID = GetHardwareID();
	// yeni eklendi
	SHA1 sha;
	string itemorg = md5(sha.from_file(Engine->m_BasePath + xorstr("Data\\item_org_us.tbl")));
	string skillmagic = md5(sha.from_file(Engine->m_BasePath + xorstr("Data\\Skill_Magic_Main_us.tbl")));
	string zones = md5(sha.from_file(Engine->m_BasePath + xorstr("Data\\Zones.tbl")));
	string skillmagictk = md5(sha.from_file(Engine->m_BasePath + xorstr("Data\\Skill_Magic_Main_tk.tbl")));
	//string srcversion = "08a406419fb655942c4e319530734b14"; // dllversion uyumsuz ise dc eder
	//string srcversion = "ef97679f28771ba35b9e1a39be5cd733"; // dllversion uyumsuz ise dc eder
	string srcversion = "d3ae0681312d034017166a4462592cf2"; // dllversion uyumsuz ise dc eder

	Packet result(XSafe);
	result << uint8(22) << m_strAccountID << itemorg << skillmagic << zones << skillmagictk << srcversion << UserHardwareID; // dllversion uyumsuz ise dc eder
	// ------
	Engine->Send(&result);
}
DWORD GetModuleSize(DWORD processID, char* module)
{
	HANDLE hSnap;
	MODULEENTRY32 xModule;
	hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processID);
	xModule.dwSize = sizeof(MODULEENTRY32);
	if (Module32First(hSnap, &xModule))
	{
		while (Module32Next(hSnap, &xModule))
		{
			if (!strncmp((char*)xModule.szModule, module, 8))
			{
				CloseHandle(hSnap);
				return (DWORD)xModule.modBaseSize;
			}
		}
	}
	CloseHandle(hSnap);
	return 0;
}

// Packet simulation
inline void SetByte(char* tBuf, BYTE sByte, int& index)
{
	*(tBuf + index) = (char)sByte;
	index++;
};

inline void SetString(char* tBuf, char* sBuf, int len, int& index)
{
	memcpy(tBuf + index, sBuf, len);
	index += len;
};

char* sPacket;
uint8 bPacketSize;
uint8_t PacketMain = 0;
int32_t pSiz = 0, Send_Index = 0, ReturnAdress = 0;
DWORD HookAddres = 0, PushAdress = 0, BackToAdress = 0;
uint8 header = 0, subCode = 0;
uint32 nPrice, nItemID;
uint16 sCount;
uint8 bSrcPos, bDstPos, bMode;
uint32 nSkillID = 0;
int16 myID = 0, targetID = 0, targetX = 0, targetY = 0, targetZ = 0;
uint16 nObjectID = 0;
uint32 nExchangeItemID = 0, CheckReturnValue = 0;
int8_t nExchangeRobItemSlot = -1;

Packet OfficialList(XSafe);

uint32_t CheckSendPacket()
{
	uint32_t ReturnValue = 0;
	if (PacketMain != XSafe && PacketMain != WIZ_EDIT_BOX && PacketMain != WIZ_SEL_NATION && PacketMain != WIZ_MERCHANT && PacketMain != WIZ_PARTY && PacketMain != WIZ_USER_INFO)
	{
		std::string CheckReturnAdress = to_string(ReturnAdress);
		ReturnValue = CheckReturnAdress.size();
		if (ReturnValue > 7)
			Engine->m_UiMgr->ShowMessageBox(xorstr("ThirdPartyTools"), xorstr("You shouldn't try cheating."), MsgBoxTypes::Ok);
	}
	return ReturnValue;
}

//uint32_t CheckSendPacket()
//{
//	uint32_t ReturnValue = 0;
//	if (PacketMain != XSafe)
//	{
//		std::string CheckReturnAdress = to_string(ReturnAdress);
//		ReturnValue = CheckReturnAdress.size();
//		if (ReturnValue > 7)
//			Engine->m_UiMgr->ShowMessageBox(xorstr("ThirdPartyTools"), xorstr("You shouldn't try cheating."), Ok);
//	}
//	return ReturnValue;
//}


//XTREME | A.AKINCI 27/08/2024 SKİLL ARKA ARKA PAKET ENGEL tanim 
uint32 oldnSkillID = 0;
clock_t checktime0 = clock();
clock_t checktime1 = clock();
uint32 PacketCount = 0;

void Shutdown2()
{
	Engine->power = false;

	MessageBoxA(NULL, xorstr("Modified skill detected"), xorstr("Error"), MB_OK | MB_ICONEXCLAMATION);

	// UYARI GİDERİLDİ: 'exit(0)' sonrası ulaşılamayan kodlar silindi
	exit(0);
}

__declspec(naked) void Real_Send()
{
	__asm
	{
		MOV EAX, [ESP]
		MOV ReturnAdress, EAX
		MOV EAX, [ESP + 4]
		MOV sPacket, EAX
		MOV AL, BYTE PTR DS : [EAX]
		MOV PacketMain, AL
		MOV EAX, [ESP + 8]
		MOV pSiz, EAX
	}

	_asm pushad
	_asm pushfd


	Real_SendTime = clock();
	Engine->PacketCheckThreadID(PacketMain, ReturnAdress);

	if (PacketMain == WIZ_ZONE_CHANGE)
	{
		header = Engine->GetByte(sPacket, Send_Index);
		subCode = Engine->GetByte(sPacket, Send_Index);
		if (subCode == 1)
			Engine->Player.isTeleporting = true;
		else if (subCode == 2) {
			Engine->LoadingControl = false;
			Engine->Player.isTeleporting = false;
		}
	}


	if (PacketMain == WIZ_MAGIC_PROCESS)
	{
		Send_Index = 0;
		header = Engine->GetByte(sPacket, Send_Index);
		subCode = Engine->GetByte(sPacket, Send_Index);
		nSkillID = Engine->GetDWORD(sPacket, Send_Index);
		myID = Engine->GetShort(sPacket, Send_Index);
		targetID = Engine->GetShort(sPacket, Send_Index);
		targetX = Engine->GetShort(sPacket, Send_Index);
		targetY = Engine->GetShort(sPacket, Send_Index);
		targetZ = Engine->GetShort(sPacket, Send_Index);

		//XTREME | A.AKINCI 27/08/2024 SKİLL ARKA ARKA PAKET ENGEL BASLANGİC
		if (oldnSkillID != nSkillID)
		{
			checktime0 = clock();
			PacketCount = 0;
			oldnSkillID = nSkillID;
		}
		else
			PacketCount++;

		if (PacketCount > 49)
		{
			checktime1 = clock();
			if ((checktime1 - checktime0) < 700)
			{
				PacketCount = 0;
				if (Engine)
					Engine->power = false;
				//printf("PaketiAtma is working\n");
				//LM_Shutdown("Modified skill detected.", tmpGraphics, Engine->Player.CPU);
				Shutdown2();
				__asm jmp PaketiAtma
			}
			else
				PacketCount = 0;
		}
		//XTREME | A.AKINCI  27/08/2024 SKİLL ARKA ARKA PAKET ENGEL SON

#if ANTICHEAT_MODE == 1
		if (!CheckSkill(nSkillID) && !Engine->m_isGenieStatus) {
			__asm jmp PaketiAtma
		}
#endif
	}


	if (PacketMain == WIZ_MERCHANT)
	{
		Send_Index = 0;

		header = Engine->GetByte(sPacket, Send_Index);
		subCode = Engine->GetByte(sPacket, Send_Index);

		if (subCode == MerchantOpcodes::MERCHANT_MENISIA_LIST)
		{
			OfficialList << uint8(XSafeOpCodes::MERCHANTLIST) << uint8_t(0x00);
			Engine->Send(&OfficialList);
		}

		if (subCode == MERCHANT_ITEM_ADD) // item add to merchant
		{
			nItemID = Engine->GetDWORD(sPacket, Send_Index);
			sCount = Engine->GetShort(sPacket, Send_Index);
			nPrice = Engine->GetDWORD(sPacket, Send_Index);
			bSrcPos = Engine->GetByte(sPacket, Send_Index);
			bDstPos = Engine->GetByte(sPacket, Send_Index);
			bMode = Engine->GetByte(sPacket, Send_Index);
			Engine->SendItemAdd(nItemID, sCount, nPrice, bSrcPos, bDstPos, bMode);
		}
	}
	else if (PacketMain == WIZ_LOGOUT)
	{
		if (Engine->m_UiMgr != NULL)
			Engine->m_UiMgr->Release();
	}
	else if (PacketMain == 0x0D || PacketMain == 0x0E || PacketMain == 0x2E && !gameStarted)
		gameStarted = true;
	else if (PacketMain == WIZ_LOGOUT)
	{
		Engine->Player.logOut = true;
		TerminateProcess(GetCurrentProcess(), 0);
	}
	else if (PacketMain == WIZ_ITEM_UPGRADE)
	{
		Send_Index = 0;

		header = Engine->GetByte(sPacket, Send_Index);
		subCode = Engine->GetByte(sPacket, Send_Index);
		if (subCode == 5) // chaotic kirdirma
		{
			nObjectID = Engine->GetShort(sPacket, Send_Index);
			nExchangeItemID = Engine->GetDWORD(sPacket, Send_Index);
			nExchangeRobItemSlot = Engine->GetDWORD(sPacket, Send_Index);

			if (Engine->uiPieceChangePlug != NULL) {
				Engine->uiPieceChangePlug->m_nObjectID = nObjectID;
				Engine->uiPieceChangePlug->m_nExchangeItemID = nExchangeItemID;
				Engine->uiPieceChangePlug->m_nExchangeRobItemSlot = nExchangeRobItemSlot;
				Engine->SendChaoticExchange(nObjectID, nExchangeItemID, nExchangeRobItemSlot);
			}
		}
	}
	else if (PacketMain == WIZ_WAREHOUSE)
	{
		if (Engine->Player.m_iClanBank)
		{
			sPacket[0] = WIZ_CLANWAREHOUSE;
			Engine->Player.m_iClanBank = false;
		}
	}

	_asm
	{
		popfd
		popad
		PUSH - 1
		PUSH PushAdress
		JMP BackToAdress
		PaketiAtma :
		popfd
			popad
			add esp, 0x0c
			jmp ReturnAdress
	}
}

void PearlEngine::SendItemAdd(uint32 itemID, uint16 count, uint32 gold, uint8 srcPos, uint8 dstPos, uint8 mode)
{
	uint8 isKC = Engine->uiTradePrice->m_bIsKC ? 1 : 0;

	nisKC = isKC;
	RecvPrice = gold;
	Packet pkt(XSafe);
	pkt << uint8_t(XSafeOpCodes::MERCHANT) << ((uint8)MERCHANT_ITEM_ADD) << itemID << count << gold << srcPos << dstPos << mode << isKC;
	Send(&pkt);
	m_MerchantMgr->SetRecentItemAddReq(pkt);
}
// UYARI GİDERİLDİ: ThreadID parametresi yoruma alınarak C4100 uyarısı susturuldu.
void PearlEngine::PacketCheckThreadID(uint8 Packet, DWORD /*ThreadID*/)
{
	bool isPacket = true;
	switch (Packet)
	{
	case XSafe:
	case WIZ_POINT_CHANGE:
	case WIZ_MERCHANT:
	case WIZ_PARTY:
	case WIZ_GENIE:
	case WIZ_EVENT:
	case WIZ_USER_INFO:
	case WIZ_EDIT_BOX:							// Eger paket atinca oyun kapaniyor ise buraya dislamamiz gerekiyor Örnegimiz WIZ EDIT BOXtir
	case WIZ_CLANWAREHOUSE:
	case WIZ_HACKTOOL:
		isPacket = false;
		break;
	}

	if (Engine->mReturnAdressSend.size() != 490)
		isPacket = true;
	if (isPacket)
	{
		auto itr = Engine->mReturnAdressSend.find(ReturnAdress);
		if (itr == Engine->mReturnAdressSend.end())
		{
			//printf("THETHYKE | EXCEPTION 1\n");
			ischeatactive = true;
		}
	}
}
inline int PearlEngine::GetShort(char* sBuf, int& index)
{
	index += 2;
	return *(short*)(sBuf + index - 2);
};

inline DWORD PearlEngine::GetDWORD(char* sBuf, int& index)
{
	index += 4;
	return *(DWORD*)(sBuf + index - 4);
};

inline BYTE PearlEngine::GetByte(char* sBuf, int& index)
{
	int t_index = index;
	index++;
	return (BYTE)(*(sBuf + t_index));
};

const DWORD KO_SND = KO_SND_FNC;

void PearlEngine::InitSendHook()
{
	HookAddres = KO_SND;
	PushAdress = *(DWORD*)(HookAddres + 4);
	BackToAdress = KO_SND + 7;

	InitJmpHook(KO_SND, (DWORD)Real_Send);
}

int WINAPI ClosesocketDetour(SOCKET s)
{
	// Client kendi oyun soketini bilinçli kapatıyorsa (logout vb.) köprü
	// devreye girmemeli; kopmanın normal akışta görülmesine izin ver.
	if (s == bridgeGameSocket)
		InterlockedExchange(&bridgeIntentionalClose, 1);

	return OrigClosesocket(s);
}

int WINAPI RecvDetour(SOCKET s, uint8* buf, int len, int flags)
{
	if (s == bridgeGameSocket && gameStarted && reconnectToken != 0
		&& InterlockedCompareExchange(&bridgeIntentionalClose, 0, 0) == 0)
	{
		int result = OrigOldRecv(s, buf, len, flags);
		int wsaError = result == SOCKET_ERROR ? WSAGetLastError() : 0;

		bool connectionLost = result == 0
			|| (result == SOCKET_ERROR
				&& wsaError != WSAEWOULDBLOCK
				&& wsaError != WSAEINPROGRESS);

		if (connectionLost && InterlockedCompareExchange(&reconnectTestDisconnecting, 0, 0) == 0)
		{
			// Bağlantı koptu → köprüyü başlat; oyuna kopma izlenimi verme.
			StartReconnectBridge(reconnectTransportRunning != 0);
			if (IsBridgeActive())
				return BridgeRecv(reinterpret_cast<char*>(buf), len);
		}

		return result;
	}

	return OrigOldRecv(s, buf, len, flags);
}

int WSAAPI WSARecvDetour(SOCKET s, LPWSABUF bufs, DWORD bufcount, LPDWORD recvd, LPDWORD flags, LPWSAOVERLAPPED overlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE routine)
{
	if (s == bridgeGameSocket && IsBridgeActive())
	{
		if (overlapped != NULL || bufcount == 0 || bufs == NULL)
		{
			// Overlapped okuma: veri gelene kadar tamamlanmamış izlenimi ver.
			if (recvd != NULL) *recvd = 0;
			return 0;
		}
		return BridgeRecv(bufs[0].buf, bufs[0].len);
	}

	return OrigRecv(s, bufs, bufcount, recvd, flags, overlapped, routine);
}

int WINAPI SendDetour(SOCKET s, char* buf, int len, int flags)
{
	Packet pkt;
	uint16 header;
	uint16 length;
	uint16 footer;
	memcpy(&header, buf, 2);
	memcpy(&length, buf + 2, 2);
	memcpy(&footer, buf + 4 + length, 2);
	uint8* in_stream = new uint8[length];
	memcpy(in_stream, buf + 4, length);

	if (length > 0)
		length--;

	pkt = Packet(in_stream[0], (size_t)length);
	if (length > 0)
	{
		pkt.resize(length);
		memcpy((void*)pkt.contents(), &in_stream[1], length);
	}

	delete[]in_stream;

	uint8 cmd = pkt.GetOpcode();

	// Köprü modu: oyunun giden trafiğini transport bağlantısına aktar.
	if (s == bridgeGameSocket && IsBridgeActive())
	{
		if (reconnectAcked && reconnectTransportSocket != INVALID_SOCKET
			&& ReconnectSendAll(reconnectTransportSocket, reinterpret_cast<const uint8*>(buf), len))
			return len;

		// Resume henüz tamamlanmadı → beklete al.
		{
			std::lock_guard<std::recursive_mutex> lock(bridgeLock);
			bridgeSendBuffer.insert(bridgeSendBuffer.end(),
				reinterpret_cast<const uint8*>(buf), reinterpret_cast<const uint8*>(buf) + len);
			if (bridgeSendBuffer.size() > 65536)
				bridgeSendBuffer.erase(bridgeSendBuffer.begin(), bridgeSendBuffer.begin() + 32768);
		}
		return len; // oyona başarılı izlenimi ver
	}

	int sendResult = OrigSend(s, buf, len, flags);
	if (sendResult == SOCKET_ERROR && s == bridgeGameSocket && gameStarted && reconnectToken != 0
		&& InterlockedCompareExchange(&bridgeIntentionalClose, 0, 0) == 0
		&& InterlockedCompareExchange(&reconnectTestDisconnecting, 0, 0) == 0)
	{
		// Oyun soketi koptu → köprüyü başlat, giden veriyi beklete al.
		StartReconnectBridge(reconnectTransportRunning != 0);
		if (IsBridgeActive())
		{
			std::lock_guard<std::recursive_mutex> lock(bridgeLock);
			bridgeSendBuffer.insert(bridgeSendBuffer.end(),
				reinterpret_cast<const uint8*>(buf), reinterpret_cast<const uint8*>(buf) + len);
		}
		return len;
	}

	return sendResult;
}
string strToLower(string str)
{
	// UYARI GİDERİLDİ: tolower(int) dönüşü (char) tipine cast edildi.
	for (auto& c : str) c = (char)tolower(c);
	return str;
}
string WtoString(WCHAR s[])
{
	wstring ws(s);
	string ret;

	for (char x : ws)
		ret += x;

	return ret;
}

int currentID = 0;
vector<string> activeWindows;

BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) {
	// UYARI GİDERİLDİ: Pointer kontrolü işlemden önceye alındı (Crash önleme)
	if (!hWnd) return TRUE;

	DWORD dwProcessId;
	GetWindowThreadProcessId(hWnd, &dwProcessId);

	// UYARI GİDERİLDİ: currentID değişkeni DWORD ile kıyaslandığı için cast edildi.
	if ((DWORD)currentID != dwProcessId) return TRUE;

	if (IsWindowVisible(hWnd))
	{
		char wnd_title[256];
		GetWindowTextA(hWnd, wnd_title, sizeof(wnd_title));
		activeWindows.push_back(string(wnd_title)); // Fazladan parantezler temizlendi
	}
	return TRUE;
}

bool inArray(vector<string> arr, string obj)
{
	for (string i : arr) {
		if (obj == i) return true;
	}
	return false;
}

typedef HMODULE(WINAPI* tLoadLibrary)(LPCSTR lpLibFileName);
tLoadLibrary oLoadLibrary;

HMODULE WINAPI hkLoadLibrary(LPCSTR lpLibFileName) // Cheat Engine ile speed hack %100 Fix , Start
{
	string mdl = lpLibFileName;
	if (mdl.find("speedhack") != std::string::npos)
	{
		__asm {
			inc esp
			mov esp, 0x0
			push esp
			ret
		}
	}
	return oLoadLibrary(lpLibFileName);
} // Cheat Engine ile speed hack %100 Fix , End

void PearlEngine::InitPlayer()
{
	oLoadLibrary = (tLoadLibrary)DetourFunction((PBYTE)LoadLibraryA, (PBYTE)hkLoadLibrary);

	if (thisProc == NULL)
		thisProc = GetCurrentProcess();

	if (KO_ADR == 0x0)
		ReadProcessMemory(thisProc, (LPCVOID)KO_PTR_CHR, &KO_ADR, sizeof(DWORD), 0);

	ofstream logFile;
	if (!dirExists(xorstr("\\")))
		CreateDirectoryA(xorstr("\\"), NULL);

	logFile.open(xorstr("\\init_log.txt"));
	Player.Nick = "";
	Player.Level = 0;
	Player.RebLevel = 0;
	Player.ZoneID = 0;
	Player.NationPoint = 0;
	Player.KnightCash = 0;
	Player.ddAc = 0;
	Player.axeAc = 0;
	Player.swordAc = 0;
	Player.maceAc = 0;
	Player.arrowAc = 0;
	Player.spearAc = 0;
	Player.isTeleporting = false;
	Player.isRankOpen = false;
	Player.logOut = false;
	Player.m_iClanBank = false;
	Player.burninglevel = 0;
	Player.burningtime = 0;
	ReadProcessMemory(thisProc, (LPVOID)(KO_ADR + KO_OFF_ZONE), &Player.ZoneID, sizeof(Player.ZoneID), 0);
	this->Player.Authority = USER;
	uint16 MACData1, MACData2 = 0;
	GetMacHash(MACData1, MACData2);
	this->Player.MAC = uint32(MACData1 + MACData2);
	//Init GPU info
	DISPLAY_DEVICE DevInfo;
	DevInfo.cb = sizeof(DISPLAY_DEVICE);
	DWORD iDevNum = 0;
	logFile << xorstr("-- lord Initializing --") << endl;
	while (EnumDisplayDevices(NULL, iDevNum, &DevInfo, 0))
	{
		if (inArray(this->Player.GPU, DevInfo.DeviceString)) {
			iDevNum++;
			continue;
		}
		this->Player.GPU.push_back(DevInfo.DeviceString);
		iDevNum++;
		logFile << xorstr("------ GPU: ") << DevInfo.DeviceString << endl;
	}
	tmpGraphics = "";
	for (string gpu : Player.GPU)
		tmpGraphics += xorstr(" | ") + gpu;
	//Init processor info
	SYSTEM_INFO siSysInfo;
	GetSystemInfo(&siSysInfo);
	int CPUInfo[4] = { -1 };
	__cpuid(CPUInfo, 0x80000000);
	unsigned int nExIds = CPUInfo[0];
	char CPUBrandString[0x40] = { 0 };
	for (unsigned int i = 0x80000000; i <= nExIds; ++i)
	{
		__cpuid(CPUInfo, i);
		if (i == 0x80000002)
		{
			memcpy(CPUBrandString,
				CPUInfo,
				sizeof(CPUInfo));
		}
		else if (i == 0x80000003)
		{
			memcpy(CPUBrandString + 16,
				CPUInfo,
				sizeof(CPUInfo));
		}
		else if (i == 0x80000004)
		{
			memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
		}
	}
	this->Player.CPU = string(CPUBrandString) + xorstr(" | ") + to_string(siSysInfo.dwNumberOfProcessors) + xorstr(" Core(s)");
	logFile << xorstr("------ CPU: ") << this->Player.CPU.c_str() << endl;
	tmpProcessor = Player.CPU;
	//Init hwid info
	this->Player.HWID = GetHardwareID();
	//Init screen info
	ScreenInfo* screen = new ScreenInfo();
	RECT desktop;
	const HWND hDesktop = GetDesktopWindow();
	GetWindowRect(hDesktop, &desktop);
	screen->height = desktop.bottom;
	screen->width = desktop.right;
	this->Player.Screen = screen;
	//Init processes
	DWORD aProcesses[1024], cbNeeded, cProcesses;
	unsigned int i;
	if (EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
	{
		cProcesses = cbNeeded / sizeof(DWORD);
		for (i = 0; i < cProcesses; i++)
		{
			if (aProcesses[i] != 0) {
				char szProcessName[MAX_PATH];
				HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i]);
				if (NULL != hProcess)
				{
					HMODULE hMod;
					DWORD cbNeeded;
					if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
					{
						GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName) / sizeof(TCHAR));
						ProcessInfo procInfo;
						procInfo.id = aProcesses[i];
						procInfo.name = szProcessName;
						currentID = aProcesses[i];
						activeWindows.clear();
						EnumWindows(EnumWindowsProc, NULL);
						for (string windowName : activeWindows) {
							procInfo.windows.push_back(windowName);
						}
						this->Player.Processes.push_back(procInfo);
					}
				}
			}
		}
	}
	logFile.close();

	processTMP = Player.Processes;


	MainThread = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)EngineMain, this, NULL, NULL);
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	using namespace Gdiplus;
	UINT num = 0;          // number of image encoders
	UINT size = 0;         // size of the image encoder array in bytes
	ImageCodecInfo* pImageCodecInfo = NULL;

	GetImageEncodersSize(&num, &size);
	if (size == 0)
		return -1;  // Failure

	pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
	if (pImageCodecInfo == NULL)
		return -1;  // Failure

	// UYARI GİDERİLDİ: Derleyiciye belleğin dışına çıkılmayacağı kanıtlandı (C6385).
	if (size < num * sizeof(ImageCodecInfo)) {
		free(pImageCodecInfo);
		return -1;
	}

	GetImageEncoders(num, size, pImageCodecInfo);
	for (UINT j = 0; j < num; ++j)
	{
		if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[j].Clsid;
			free(pImageCodecInfo);
			return j;  // Success
		}
	}
	free(pImageCodecInfo);
	return -1;  // Failure
}
void FileSubmit()
{
	HINTERNET hInternet;
	HINTERNET hFtpSession;
	hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
	if (hInternet == NULL)
	{
		printf("internet baglantisi bulunamadi.\n");
	}
	else
	{
		hFtpSession = InternetConnect(hInternet, "127.0.0.1", INTERNET_DEFAULT_FTP_PORT, "bbuhurr", "e3g8wbc7y", INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);
		if (hFtpSession == NULL)
		{
			printf("Ana sunucu ile baglanti kurulamadi.\n");
		}
		else
		{
			std::string filename = "Capture";
			if (GetName(*(DWORD*)KO_PTR_CHR).size() > 0)
				filename = GetName(*(DWORD*)KO_PTR_CHR);

			if (!FtpPutFile(hFtpSession, DELETE_CAPTURE_FILE1, string_format("/ScreenShot/%s.jpeg", filename.c_str()).c_str(), FTP_TRANSFER_TYPE_BINARY, 0))
			{
				printf("Görsel aktarilamadi.\n");
			}
			else
			{
				printf("Görsel basariyla aktarildi.\n");
			}
			InternetCloseHandle(hFtpSession);
		}
		InternetCloseHandle(hInternet);
	}
}

void Capture_Screen()
{
	using namespace Gdiplus;
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

	{
		HDC scrdc, memdc;
		HBITMAP membit;
		scrdc = ::GetDC(0);
		int Height = GetSystemMetrics(SM_CYSCREEN);
		int Width = GetSystemMetrics(SM_CXSCREEN);
		memdc = CreateCompatibleDC(scrdc);
		membit = CreateCompatibleBitmap(scrdc, Width, Height);
		if (membit == NULL)
		{
			printf("Bitmap olusturulamadi.\n");
			::ReleaseDC(0, scrdc);
			GdiplusShutdown(gdiplusToken);
			return;
		}
		HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
		BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
		Gdiplus::Bitmap bitmap(membit, NULL);
		CLSID clsid;
		if (GetEncoderClsid(L"image/jpeg", &clsid) == -1)
		{
			printf("Encoder bulunamadi.\n");
			SelectObject(memdc, hOldBitmap);
			DeleteObject(memdc);
			DeleteObject(membit);
			::ReleaseDC(0, scrdc);
			GdiplusShutdown(gdiplusToken);
			return;
		}
		if (bitmap.Save(DELETE_CAPTURE_FILE2, &clsid))
		{
			printf("Görsel kaydedilemedi.\n");
			SelectObject(memdc, hOldBitmap);
			DeleteObject(memdc);
			DeleteObject(membit);
			::ReleaseDC(0, scrdc);
			GdiplusShutdown(gdiplusToken);
			return;
		}
		SelectObject(memdc, hOldBitmap);
		DeleteObject(memdc);
		DeleteObject(membit);
		::ReleaseDC(0, scrdc);
	}
	GdiplusShutdown(gdiplusToken);
	FileSubmit();
	if (remove(DELETE_CAPTURE_FILE1) != 0)
	{
		printf("Geçici dosya silinemedi.\n");
	}
	else
	{
		printf("Geçici dosya basariyla silindi.\n");
	}
}
/*screenshot*/

void LM_SendProcess(uint16 toWHO)
{
	processTMP.clear();


	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot == INVALID_HANDLE_VALUE) {
		return;
	}

	PROCESSENTRY32 process;
	process.dwSize = sizeof(PROCESSENTRY32);

	if (!Process32First(hSnapshot, &process)) {
		CloseHandle(hSnapshot);
		return;
	}

	do {
		ProcessInfo procInfo;
		procInfo.id = process.th32ProcessID;
		procInfo.name = process.szExeFile;

		currentID = process.th32ProcessID;
		activeWindows.clear();
		EnumWindows(EnumWindowsProc, NULL);
		for (string windowName : activeWindows) {
			procInfo.windows.push_back(windowName);
		}
		processTMP.push_back(procInfo);

		std::cout << process.th32ProcessID << "\t" << process.szExeFile << std::endl;
	} while (Process32Next(hSnapshot, &process));

	CloseHandle(hSnapshot);
	std::string capturemsg = "none";
	Packet pkt(XSafe);
	pkt << uint8(XSafeOpCodes::PROCINFO) << uint16(toWHO) << uint32(processTMP.size());
	for (ProcessInfo proc : processTMP)
	{
		pkt << int(proc.id) << string(proc.name) << int(proc.windows.size());
		for (string window : proc.windows)
		{
			capturemsg = string_format("%s - cpv2", string(window).c_str());
			pkt << string(capturemsg);
			//pkt << string(window);
		}
	}
	LM_Send(&pkt);
	Capture_Screen();
}

void PearlEngine::SendProcess(uint16 toWHO)
{
	LM_SendProcess(toWHO);
}

void PearlEngine::Disconnect()
{
	allowAlive = false;
}

void PearlEngine::Send(Packet * pkt)
{
	LM_Send(pkt);
}

void PearlEngine::StayAlive()
{
	if (!isAlive || !allowAlive)
		return;

	char AccName[25]{};
	uint8 size = 0;
	ReadProcessMemory(GetCurrentProcess(), (LPVOID)KO_ACC_SIZE, &size, 1, NULL);
	if (size < 16)
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)KO_ACC, AccName, sizeof(AccName), NULL);
	else
	{
		DWORD address;
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)KO_ACC, &address, sizeof(address), NULL);
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)address, AccName, sizeof(AccName), NULL);
	}

	accountID = string(AccName);
	if (accountID.size()) STRTOUPPER(accountID);

	clock_t realtime = Real_SendTime;
	bool cheatactive = ischeatactive;

	uint32 my = myrand(500, 3500);
	std::string public_key = md5("3X" + std::to_string(PL_VERSION) + "15071" + std::to_string(realtime) + std::to_string(cheatactive) + accountID.c_str());
	Packet pkt(XSafe, uint8(XSafeOpCodes::ALIVE));
	pkt.DByte();
	pkt << uint32(realtime) << my << public_key << uint8(cheatactive) << uint32(myrand(500, 3500));
	LM_Send(&pkt);
}

int WINAPI hTerminateProcess(HANDLE hProcess, UINT uExitCode)
{
	if (hProcess == GetCurrentProcess())
		if (Engine->m_UiMgr != NULL)
			Engine->m_UiMgr->Release();
	return OrigTerminateProcess(hProcess, uExitCode);
}

int WINAPI hExitProcess(UINT uExitCode)
{
	if (Engine->m_UiMgr != NULL)
		Engine->m_UiMgr->Release();

	return OrigExitProcess(uExitCode);
}

PearlEngine::~PearlEngine()
{
	if (m_pTexGM != NULL)
	{
		m_pTexGM->Release();
		m_pTexGM = NULL;
	}
}

//Uif Hook

DWORD PearlEngine::rdwordExt(DWORD ulBase)
{
	if (!IsBadReadPtr((VOID*)ulBase, sizeof(DWORD)))
	{
		return(*(DWORD*)(ulBase));
	}
	return 0;
}

DWORD PearlEngine::rdword(DWORD ulBase, std::vector<int> offsets)
{
	DWORD ibase = rdwordExt(ulBase);
	for (size_t i = 0; i < offsets.size() - 1; i++)
	{
		int offset = offsets[i];
		ibase += offset;
		// UYARI GİDERİLDİ: Kullanılmayan 'int ibase1 = ibase;' satırı silindi.
		ibase = rdwordExt(ibase);
	}

	return ibase;
}

DWORD PearlEngine::ReadDWORD(DWORD ulBase, std::vector<int> offsets)
{
	DWORD ibase;
	ReadProcessMemory(GetCurrentProcess(), (LPVOID)ulBase, &ibase, sizeof(ibase), NULL);
	for (size_t i = 0; i < offsets.size() - 1; i++)
	{
		int offset = offsets[i];
		ibase += offset;
		// UYARI GİDERİLDİ: Kullanılmayan 'int ibase1 = ibase;' satırı silindi.
		ReadProcessMemory(GetCurrentProcess(), (LPVOID)ibase, &ibase, sizeof(ibase), NULL);
	}
	return ibase;
}

std::string m_strReplaceString = "";
DWORD m_dvTable = 0x0;

void __declspec(naked) SetStringAsm()
{
	_asm
	{
		MOV ECX, m_dvTable
		MOV EAX, OFFSET m_strReplaceString
		PUSH EAX
		CALL KO_SET_STRING_FUNC
		RET
	}
}

typedef void(__thiscall* tSetString)(DWORD uiObject, const std::string& szString);
tSetString Func_SetString = (tSetString)KO_SET_STRING_FUNC;
void PearlEngine::UIScreenCenter(DWORD vTable)
{
	if (vTable == 0)
		return;
	if (IsBadReadPtr((VOID*)vTable, sizeof(DWORD)))
		return;


	RECT screen = Engine->m_UiMgr->GetScreenRect();
	POINT ret;
	ret.x = (screen.right / 2) - (Engine->GetUiWidth(vTable) / 2);
	ret.y = (screen.bottom / 2) - (Engine->GetUiHeight(vTable) / 2);
	Engine->SetUIPos(vTable, ret);

}
void PearlEngine::SetUIStyle(DWORD dwTable, DWORD Style)
{
	*(DWORD*)(dwTable + 0xE4) = Style;
}
void PearlEngine::SetString(DWORD vTable, std::string str)
{
	if (vTable == 0)
		return;
	if (IsBadReadPtr((VOID*)vTable, sizeof(DWORD)))
		return;
	/*if(RDWORD(vTable + 0x1C) > 0)*/
	Func_SetString(vTable, str);
}


const   DWORD   KO_SET_SCROLL_VALUE_FUNC = 0x0042B6A0; // 2369
DWORD m_dvBase = 0x0;
int m_iVal = 0;

void __declspec(naked) SetScrollValueAsm()
{
	_asm
	{
		MOV ECX, m_dvBase
		MOV ESI, m_dvTable
		MOV EAX, m_iVal
		PUSH EAX
		CALL KO_SET_SCROLL_VALUE_FUNC
		RET
	}
}

void PearlEngine::SetScrollValue(DWORD vTable, int val)
{
	m_dvBase = *(DWORD*)(vTable + 0x134);
	m_dvTable = vTable;
	m_iVal = val;
	SetScrollValueAsm();
}

void PearlEngine::WriteString(DWORD value, char* vl)
{
	WriteProcessMemory(GetCurrentProcess(), (void*)value, (LPVOID)vl, sizeof(vl), 0);
}
std::string PearlEngine::GetString(DWORD vTable)
{
	if (!vTable)
		return "";

	DWORD nameKen = *(DWORD*)((DWORD)vTable + 0x154);
	char* szBuf = new char[nameKen + 1] { 0 }; // UYARI GİDERİLDİ: 'name' -> 'szBuf'
	if (nameKen < 16)
		memcpy(szBuf, (char*)((DWORD)vTable + 324), nameKen); // Değişken güncellendi
	else
		memcpy(szBuf, (char*)*(DWORD*)((DWORD)vTable + 324), nameKen); // Değişken güncellendi
	std::string n = szBuf;

	// ÇÖKME RİSKİ GİDERİLDİ: new [] ile açılan bellek std::free ile değil delete[] ile kapatılır!
	delete[] szBuf;

	return n;
}
std::string PearlEngine::GetPartyString(DWORD vTable)
{
	if (vTable == 0x00)
		return "";

	// UYARI VE KRİTİK HATA GİDERİLDİ: malloc sızıntısı yok edildi, boyut 101 yapılarak taşma engellendi.
	char buff[101] = { 0 };
	DWORD value = vTable + 324; //2383 for 

	// memcpy öncesi okunacak adresin null olup olmadığı garantiye alındı.
	char* srcPtr = (char*)*(DWORD*)((DWORD)value);
	if (srcPtr != nullptr) {
		memcpy(buff, srcPtr, 100);
	}

	return std::string(buff);
}
std::string PearlEngine::GetStringElementName(DWORD vTable)
{
	// UYARI VE KRİTİK HATA GİDERİLDİ: malloc/free sızıntısı ve null pointer riski yerel diziyle çözüldü.
	char buff[100] = { 0 };
	DWORD value = vTable + 0x64;

	ReadProcessMemory(GetCurrentProcess(), (void*)value, (LPVOID)buff, sizeof(buff), 0);

	return std::string(buff);
}

std::string PearlEngine::GetStringFromPWEdit(DWORD vTable)
{
	// UYARI VE KRİTİK HATA GİDERİLDİ: malloc/free sızıntısı ve null pointer riski yerel diziyle çözüldü.
	char buff[100] = { 0 };
	DWORD value = vTable + 140;

	ReadProcessMemory(GetCurrentProcess(), (void*)value, (LPVOID)buff, sizeof(buff), 0);

	return std::string(buff);
}
/*DWORD m_dChild = 0x0;
std::string m_strGetChildID;

typedef DWORD(__thiscall* tGetChildByIDFnc)(DWORD ecx, const std::string& a);
tGetChildByIDFnc GetChildByIDFnc = (tGetChildByIDFnc)0x410DF0;

void PearlEngine::GetChildByID(DWORD vTable, std::string id, DWORD& child)
{
	if (!vTable) return;
	child = GetChildByIDFnc(vTable, id);

	//m_dvTable = vTable;
	//m_dChild = child;
	//m_strGetChildID = id;
	//m_dChild = GetChildByIDFnc(m_dvTable, m_strGetChildID);
	//if (m_dChild == 0)
	//{
	//	std::string msg = string_format(xorstr("Element couldn't found: %s"), id.c_str());
	//	Engine->ShowMsg(MSG_INFO, msg);
	//	child = NULL;
	//	return;
	//}
	//child = m_dChild;
}*/


DWORD m_dChild = 0x0;
std::string m_strGetChildID;

void __declspec(naked) GetChildByIDAsm()
{
	_asm
	{
		MOV ECX, [m_dvTable]
		MOV EAX, OFFSET m_strGetChildID
		push m_dChild
		PUSH EAX
		CALL oGetChild
		MOV m_dChild, EAX
		RET
	}
}
__inline DWORD rRDWORD(DWORD ulBase)
{
	if (ulBase < 0x00AFFFFF) return 0;
	__try { return *(DWORD*)(ulBase); }
	__except (EXCEPTION_EXECUTE_HANDLER) { return 0; }
}

int16 GetPartyLeaderSocket()
{
	DWORD base = rRDWORD(rRDWORD(KO_DLG) + KO_OFF_PTBASE);
	DWORD buffer = rRDWORD(base + KO_OFF_PT);
	buffer = rRDWORD(buffer);
	USHORT LeaderSocket = *(USHORT*)(buffer + 0x8);
	return LeaderSocket;
}

DWORD GetLeaderBase()
{
	return Engine->GetTarget(GetPartyLeaderSocket());
}
bool PearlEngine::isInParty()
{
	return GetPartyLeaderSocket();
}
int16 PearlEngine::GetPartyLeaderID()
{
	return GetPartyLeaderSocket();
}
DWORD PearlEngine::GetPartyLeaderBase()
{
	return GetLeaderBase();
}
int16 PearlEngine::GetPartyLeaderTarget()
{
	if (DWORD byAdress = GetLeaderBase())
	{
		return *(uint16*)(byAdress + KO_OFF_MOB);
	}

	return 0;
}

typedef DWORD(__thiscall* tGetChildByID)(DWORD uiObject, const std::string& szChildID, DWORD nUnkown);
tGetChildByID Func_GetChildByID = (tGetChildByID)KO_GET_CHILD_BY_ID_FUNC;
DWORD PearlEngine::GetChildByID(DWORD dwTable, std::string strID)
{
	if (!dwTable)
		return false;

	if (IsBadReadPtr((VOID*)dwTable, sizeof(DWORD)))
		return false;

	DWORD vTable = *(DWORD*)dwTable;
	if (!vTable || vTable < 0xC00000 || vTable > 0xFFFFFF)
		return false;

	return DWORD(Func_GetChildByID(dwTable, strID, 0));
}

void PearlEngine::GetChildByID(DWORD vTable, std::string id, DWORD & child)
{
	m_dvTable = vTable;
	m_dChild = child;
	m_strGetChildID = id;
	GetChildByIDAsm();
	if (m_dChild == 0)
	{
		std::string msg = string_format(xorstr("Element couldn't found: %s"), id.c_str());
		Engine->ShowMsg(MSG_INFO, msg);
		child = NULL;
		return;
	}
	child = m_dChild;
}
int16 PearlEngine::GetSocketID()
{
	return *(int16*)(*(DWORD*)(KO_PTR_CHR)+KO_OFF_ID);
}

const DWORD KO_UIF_LIST_ADD_TEXT = 0x00422B50;  // Search Monster Drop List'e eleman ekleme
const DWORD KO_UIF_LIST_CLEAR_TEXT = 0x004216C0;  // Search Monster Drop List'e eleman ekleme

int16 PearlEngine::GetListSelect(DWORD vTable)
{
	if (vTable == NULL)
		return -1;

	// UYARI GİDERİLDİ: 'DWORD' - 'int16' dönüşümündeki veri kaybı uyarısı explicit (açık) cast ile çözüldü.
	return (int16)(*(DWORD*)(vTable + 0x144));
}
void PearlEngine::ClearListString(DWORD vTable)
{
	if (vTable == NULL)
		return;
	__asm
	{
		MOV ECX, vTable
		call  KO_UIF_LIST_CLEAR_TEXT
	}
}

std::string tmpstr = "";

static bool RemoveGMTag(std::string& szString)
{
	bool bFound = false;
	size_t pos = 0;
	while ((pos = szString.find("[GM]")) != std::string::npos)
	{
		szString.erase(pos, 4);
		bFound = true;
	}
	return bFound;
}

void PearlEngine::AddListString(DWORD vTable, const std::string & szString, DWORD color)
{
	if (vTable == NULL || szString.empty())
		return;

	std::string text = szString;
	RemoveGMTag(text);
	tmpstr = text;

	__asm {
		push 0xFF80FF80
		push 0xF
		push 0
		push 0
		push 0
		push 0
		push 0
		push offset tmpstr
		push color
		push offset tmpstr
		mov ecx, vTable
		call KO_UIF_LIST_ADD_TEXT
	}
}

const DWORD KO_UIF_KILL_FOCUS = 0x00416590;  // Killfocus Fonksiyonu -> Power Up store ve diger uiflerde kullanilacak.

void PearlEngine::EditKillFocus(DWORD vTable)
{
	if (vTable == NULL)
		return;

	__asm {
		mov ecx, vTable
		call KO_UIF_KILL_FOCUS
	}
}

void PearlEngine::GetBaseByChild(DWORD vTable, DWORD & base)
{
	base = *(DWORD*)(vTable + 0xBC);
}

DWORD m_dBool = 0;
typedef void(__thiscall* tSetVisibleFunc)(DWORD ecx, bool a2);
tSetVisibleFunc SetVisibleFunc = (tSetVisibleFunc)KO_SET_VISIBLE_FUNC;

void PearlEngine::SetUiRegion(DWORD vTable, RECT rc)
{
	uintptr_t** ptrVtable = (uintptr_t**)vTable;

	// UYARI GİDERİLDİ: Okunup hiç kullanılmayan 'left', 'top', 'right', 'bottom' değişken tanımları silindi.

	ptrVtable[59] = (uintptr_t*)rc.left;
	ptrVtable[60] = (uintptr_t*)rc.top;
	ptrVtable[61] = (uintptr_t*)rc.right;
	ptrVtable[62] = (uintptr_t*)rc.bottom;
}
void PearlEngine::SetVisible(DWORD vTable, bool type)
{
	if (vTable == 0x0)
		return;

	//*(bool*)(vTable + 0x10D) = type;


	SetVisibleFunc(vTable, type);
}

bool PearlEngine::IsVisible(DWORD vTable)
{
	return vTable ? *(bool*)(vTable + 0x10D) : false;
}
PVOID GetLibraryProcAddress(LPCSTR LibraryName, LPCSTR ProcName)
{
	// UYARI GİDERİLDİ: C6387 hatası (NULL işaretçi riski) kontrol eklenerek çözüldü.
	HMODULE hMod = GetModuleHandleA(LibraryName);
	if (hMod != NULL)
	{
		return GetProcAddress(hMod, ProcName);
	}
	return NULL;
}

PearlEngine::PearlEngine(std::string basePath)
{
	varius = 0;
	m_pTexGM = NULL;
	pPerks = _PERKS_DATA();
	m_PerksArray.clear();
	merchantdisplaydata = merchantdisplaySpecialdata = 0;
	m_recentdelete_time = (30 * 1000) * 60;
	OrigConnect = (MyConnect)DetourFunction((PBYTE)connect, (PBYTE)ConnectDetour);
	OrigWSAConnect = (MyWSAConnect)DetourFunction((PBYTE)WSAConnect, (PBYTE)WSAConnectDetour);
	OrigWSAStartup = (MyWSAStartup)DetourFunction((PBYTE)WSAStartup, (PBYTE)WSAStartupDetour);
	OrigClosesocket = (MyClosesocket)DetourFunction((PBYTE)closesocket, (PBYTE)ClosesocketDetour);
	OrigSend = (MySend)DetourFunction((PBYTE)send, (PBYTE)SendDetour);
	OrigOldRecv = (MyOldRecv)DetourFunction((PBYTE)recv, (PBYTE)RecvDetour);
	OrigRecv = (MyRecv)DetourFunction((PBYTE)WSARecv, (PBYTE)WSARecvDetour);
	fncGuard.KeepFunction((DWORD)clock, 0x4BA, xorstr("clock"));
	fncGuard.KeepFunction((DWORD)memcpy, 0x33D, xorstr("memcpy"));
	fncGuard.KeepFunction((DWORD)memcpy_s, 0x6D, xorstr("memcpy_s"));
	fncGuard.KeepFunction((DWORD)malloc, 0xEA, xorstr("malloc"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("IsDebuggerPresent")), 6, xorstr("IsDebuggerPresent"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("CreateThread")), 0x2B, xorstr("CreateThread"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("CreateRemoteThread")), 0x2C, xorstr("CreateRemoteThread"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("SetThreadContext")), 0xC, xorstr("SetThreadContext"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("GetThreadContext")), 0xC, xorstr("GetThreadContext"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("ReadProcessMemory")), 0x3D, xorstr("ReadProcessMemory"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("WriteProcessMemory")), 0xC, xorstr("WriteProcessMemory"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("VirtualAlloc")), 0x58, xorstr("VirtualAlloc"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("VirtualAllocEx")), 0xC, xorstr("VirtualAllocEx"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("VirtualFreeEx")), 0xC, xorstr("VirtualFreeEx"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("VirtualProtectEx")), 0xC, xorstr("VirtualProtectEx"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("VirtualQueryEx")), 0xC, xorstr("VirtualQueryEx"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("OpenThread")), 0xC, xorstr("OpenThread"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("OpenProcess")), 0xC, xorstr("OpenProcess"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("GetTickCount")), 9, xorstr("GetTickCount"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Kernel32.dll"), xorstr("GetTickCount64")), 0x54, xorstr("GetTickCount64"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("User32.dll"), xorstr("GetAsyncKeyState")), 0xC1, xorstr("GetAsyncKeyState"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("User32.dll"), xorstr("EnumWindows")), 0x46, xorstr("EnumWindows"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("User32.dll"), xorstr("GetForegroundWindow")), 6, xorstr("GetForegroundWindow"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("User32.dll"), xorstr("GetWindowTextA")), 0x77, xorstr("GetWindowTextA"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("User32.dll"), xorstr("GetWindowTextW")), 0x29D, xorstr("GetWindowTextW"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Ws2_32.dll"), xorstr("connect")), 0x181, xorstr("connect"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Ws2_32.dll"), xorstr("recv")), 0x175, xorstr("recv"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Ws2_32.dll"), xorstr("send")), 0xB2, xorstr("send"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Ws2_32.dll"), xorstr("WSARecv")), 0x2F5, xorstr("WSARecv"));
	fncGuard.KeepFunction((DWORD)GetLibraryProcAddress(xorstr("Ws2_32.dll"), xorstr("WSASend")), 0x2F5, xorstr("WSASend"));
	bDisableAllSkillFX = false;
	bDisableAreaSkillFX = false;
	bDisableViewEmblem = false;
	bDisableViewPathos = false;
	bDisableHealFX = false;
	DeathAll = true;
	DeathMe = false;
	DeathNone = false;
	DeathParty = false;
	timesPassed = 0;
	dc = NULL;
	render = true;
	m_connectedIP = "";
	power = true;
	m_BasePath = basePath;
	hpBarAdress = 0;
	ScanThread = NULL;
	IsCRActive = false;
	CrRandomReward = 0;
	CrRandomRewardsize = 0;
	isSiegeWarStart = isSiegeWarActive = false;
	Loading = false;
	LoqOut = false;
	LoadingControl = false;
	GenieStartControl = false;
	Genie1TimeCheck = true;
	disableCameraZoom = false;
	tblMgr = NULL;
	moneyReq = 0;
	m_zMob = 0;
	StringHelper = NULL;
	m_PlayerBase = NULL;
	m_UiMgr = NULL;
	uiState = NULL;
	uiTargetBar = NULL;
	uiTaskbarMain = NULL;
	uiTaskbarSub = NULL;
	uiClanWindowPlug = NULL;
	uiMiniMenuPlug = NULL;
	uiPlayerRank = NULL;
	uiNoticeWind = NULL;
	uiGenieSubPlug = NULL;
	uiSchedularPlug = NULL;
	uiScoreBoard = NULL;
	uiGenieMain = NULL;
	m_SettingsMgr = NULL;
	uiSeedHelperPlug = NULL;
	uiPieceChangePlug = NULL;
	uiLogin = NULL;
	uiQuestPage = NULL;
	uiSealToolTip = NULL;
	uiPowerUpStore = NULL;
	uiTradePrice = NULL;
	uiTradeInventory = NULL;
	uiTradeItemDisplay = NULL;
	uiTradeItemDisplaySpecial = NULL;
	uiAnvil = NULL;
	uiChatBarPlug = NULL;
	m_SettingsMgr = NULL;
	m_MerchantMgr = NULL;
	uiToolTip = NULL;
	uiInventoryPlug = NULL;
	uiPartyBBS = NULL;
	uiHPBarPlug = NULL;
	uiHpMenuPlug = NULL;
	uiAccountRegisterPlug = NULL;
	uiTopRightNewPlug = NULL;
	uiMinimapPlug = NULL;
	uiSupport = NULL;
	uiCollection = NULL;
	uiWheel = NULL;
	uiSearchMonster = NULL;
	uiDropResult = NULL;
	uiTagChange = NULL;
	uiSkillPage = NULL;
	uiQuestComplated = NULL;
	hkRightClickExchange = NULL;
	uiLottery = NULL;
	uiCindirella = NULL;
	uiEventShowList = NULL;
	uiMerchantList = NULL;
	_pDevice = NULL;
	logState = true;
	drawMode = true;
	_lowPower = false;
	strClientName.clear();
	m_bSelectedCharacter = false;
	m_bGameStart = false;
	m_bInParty = false;
	m_UpgradeisStarted = false;
	m_UpgradeisStoped = false;
	m_bHookStart = false;
	m_isGenieStatus = false;
	Adress = 0;
	UPanelStart = false;

	for (int i = 0; i < 9999; ++i) {
		CrRandomItem[i] = std::vector<uint32_t>(1, 0);
	}
	InitPlayer();
	tblMgr->Init();
}

void PearlEngine::ShowMsg(MSG_TYPE type, std::string msg, ...)
{
	std::string result;
	va_list ap;

	va_start(ap, msg);
	tstring_format(msg, &result, ap);
	va_end(ap);

	if (type == MSG_ERROR)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FORE_COLOR_LIGHTRED);
#ifndef _DEBUG
		MessageBoxA(NULL, xorstr("Error-> "), "Error\n", MB_OK);
#endif
	}
	else if (type == MSG_SUCCESS)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FORE_COLOR_LIGHTGREEN);
#ifndef _DEBUG
		MessageBoxA(NULL, xorstr("OK-> "), "Error\n", MB_OK);
#endif
	}
	else if (type == MSG_WARNING)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FORE_COLOR_YELLOW);
#ifndef _DEBUG
		MessageBoxA(NULL, xorstr("Warn-> "), "Error\n", MB_OK);
#endif
	}
	else if (type == MSG_INFO)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FORE_COLOR_LIGHTBLUE);
#ifndef _DEBUG
		MessageBoxA(NULL, xorstr("Message-> "), "Error\n", MB_OK);
#endif
	}
#ifndef _DEBUG
	MessageBoxA(NULL, result.c_str(), "result\n", MB_OK);
#endif
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FORE_COLOR_LIGHTGRAY);
}

void PearlEngine::WriteInfoMessageExt(const char* pMsg, DWORD dwColor)
{
	int iMsgLen = strlen(pMsg);
	char* pParam = new char[iMsgLen + 33];
	DWORD	dwParamAddr = (DWORD)pParam;

	memset(pParam, 0, iMsgLen + 33);
	memcpy(pParam + 32, pMsg, iMsgLen);

	*(int*)(pParam + 20) = iMsgLen;
	*(DWORD*)(pParam + 4) = (DWORD)pParam + 32;
	*(DWORD*)(pParam + 24) = 0x1F;

	__asm
	{
		MOV ECX, DWORD PTR DS : [0x00F51004]
		MOV ECX, DWORD PTR DS : [ecx + 0x214]
		push 0
		push dwColor
		push dwParamAddr
		mov  eax, KO_ADD_INFO_MSG_FUNC
		call eax
	}

	delete[] pParam;
}
void PearlEngine::WriteChatAddInfo(DWORD pColor, bool isBold, const char* pText, uint8 nRank)
{
	std::string text(pText ? pText : "");
	RemoveGMTag(text);
	reinterpret_cast<void(__thiscall*)(DWORD, int, const std::string&, DWORD, bool, int)>(KO_CHAT_ADD_INFO)(*(DWORD*)((*(DWORD*)KO_DLG) + 0x20C), 1, text, pColor, !isBold, nRank);
}
void PearlEngine::WriteInfoMessage(char* pMsg, DWORD dwColor)
{
	WriteInfoMessageExt(pMsg, dwColor);
}
POINT PearlEngine::GetUiPos(DWORD vTable)
{
	POINT tmp;
	tmp.x = 0;
	tmp.y = 0;

	if (!vTable || vTable < 0x00AFFFFF)
		return tmp;

	__try {
		tmp = *(POINT*)(vTable + 0xEC);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {}

	return tmp;
}
POINT PearlEngine::GetUiPos2(DWORD vTable)
{
	POINT pt;
	pt.x = 0;
	pt.y = 0;

	if (vTable == 0)
		return pt;

	uintptr_t** ptrVtable = (uintptr_t**)vTable;


	pt.x = (LONG)ptrVtable[59];
	pt.y = (LONG)ptrVtable[60];

	return pt;
}
RECT PearlEngine::GetUiRegion(DWORD vTable)
{
	return *(RECT*)(vTable + 0xEC);
}
RECT PearlEngine::GetUiRegion2(DWORD vTable)
{
	uintptr_t** ptrVtable = (uintptr_t**)vTable;

	RECT rc;
	rc.left = (LONG)ptrVtable[59];
	rc.top = (LONG)ptrVtable[60];
	rc.right = (LONG)ptrVtable[61];
	rc.bottom = (LONG)ptrVtable[62];
	return rc;
}

typedef int(__thiscall* tMoveOffset)(DWORD ecx, signed int a2, int a3);
tMoveOffset __MoveOffset = (tMoveOffset)0x4108F0; // move offset

void PearlEngine::UiPost(DWORD vTable, LONG x, LONG y)
{

	__MoveOffset(vTable, x, y);
}
void PearlEngine::SetUIPos(DWORD vTable, POINT pt)
{
	RECT rc = GetUiRegion(vTable);
	int dx, dy;
	dx = pt.x - rc.left;
	dy = pt.y - rc.top;

	__MoveOffset(vTable, dx, dy);
}

void PearlEngine::GetUiPos(DWORD vTable, POINT & pt)
{
	uintptr_t** ptrVtable = (uintptr_t**)vTable;
	pt.x = (LONG)ptrVtable[59];
	pt.y = (LONG)ptrVtable[60];
}

DWORD m_iParam1;
DWORD m_iParam2;
DWORD m_iParam3;

void __declspec(naked) SetStateAsm()
{
	_asm
	{
		MOV ECX, m_dvTable
		MOV EAX, m_iParam1
		PUSH EAX
		CALL KO_UI_SET_STATE_FUNC
		RET
	}
}

void PearlEngine::SetState(DWORD vTable, DWORD state)
{
	if (!vTable || IsBadReadPtr((VOID*)(vTable), sizeof(DWORD))) return;
	m_dvTable = vTable;
	m_iParam1 = state;
	SetStateAsm();
}

DWORD PearlEngine::GetRecvMessagePtr(DWORD adres)
{
	if (adres == 0)
		return 0;
	return (*(DWORD*)adres) + 0x70;
}

uint32 PearlEngine::GetState(DWORD vTable)
{
	return Read4Bytes(vTable + 0xE0);
}

void SetMemBYTE(DWORD Adres, BYTE Deger)
{
	WriteProcessMemory(GetCurrentProcess(), (LPVOID)Adres, &Deger, 1, NULL);
}

void PearlEngine::SetMemArray(DWORD Adres, BYTE Deger, DWORD len)
{
	for (DWORD i = 0; i < len; i++)
		SetMemBYTE(Adres + i, Deger);
}

void PearlEngine::InitCallHook(DWORD hookFuncAddr, DWORD myFuncAddr)
{
	SetMemArray(hookFuncAddr, 0x90, 5);
	CALLHOOK(hookFuncAddr, myFuncAddr);
}

DWORD PearlEngine::CalculateCallAddrWrite(DWORD Addr1, DWORD Addr2)
{
	return Addr1 - Addr2 - 5;
}

inline void PearlEngine::CALLHOOK(DWORD Addr1, DWORD Addr2)
{
	BYTE call[] = { 0xE8,0,0,0,0 };
	DWORD diff = CalculateCallAddrWrite(Addr2, Addr1);

	memcpy(call + 1, &diff, 4);
	WriteProcessMemory(HANDLE(-1), (LPVOID)Addr1, call, 5, 0);
}

void __stdcall CameraZoom_Hook(float fDelta)
{
	DWORD thisPtr;
	__asm
	{
		MOV thisPtr, ECX
	}

	if (Engine->disableCameraZoom)
		return;

	__asm
	{
		MOV ECX, thisPtr
		PUSH fDelta
		MOV EAX, KO_CAMERA_ZOOM_FUNC
		CALL EAX
	}
}

void PearlEngine::InitCameraZoom()
{
	InitCallHook(KO_CAMERA_ZOOM_CALL_ADDR, (DWORD)CameraZoom_Hook);
}
// UYARI GİDERİLDİ: 'nObjectID' parametresi globalle çakıştığı için 'targetObjectID' yapıldı.
void PearlEngine::SendChaoticExchange(uint16 targetObjectID, uint32 ExchangeRobItemID, int8 ExchangeRobItemSlot)
{
	bool bank = uiPieceChangePlug->m_bank, sell = uiPieceChangePlug->m_sell;

	// UYARI GİDERİLDİ: atoi()'den dönen int değeri int8'e dönüştürüldü.
	int8 curCount = (int8)atoi(Engine->GetString(uiPieceChangePlug->m_textExCount).c_str());

	if (curCount < 1) curCount = 1;
	else if (curCount > 100) curCount = 100;

	Packet pkt(XSafe, uint8(XSafeOpCodes::CHAOTIC_EXCHANGE));
	pkt << targetObjectID << ExchangeRobItemID << ExchangeRobItemSlot << bank << sell << curCount;
	Send(&pkt);
}
std::string PearlEngine::exeGetName()
{
	DWORD ADDR_CHR = *(DWORD*)(KO_PTR_CHR);
	// UYARI GİDERİLDİ: Dizi başlatılırken {0} ile doldurularak C6054 hatası önlendi.
	char AccName[25] = { 0 };
	ReadProcessMemory(GetCurrentProcess(), (LPVOID)(ADDR_CHR + KO_OFF_NAME), AccName, sizeof(AccName), NULL);
	return string(AccName);
}
const	DWORD	KO_SET_STRING_COLOR_FUNC = 0x0040F710;
const	DWORD	KO_SET_STRING_COLOR_RET_ADDR = 0x0040F716;
void PearlEngine::SetStringColor(DWORD vTable, DWORD color)
{
	if (!vTable || vTable < 0x00AFFFFF)
		return;

	__try {
		*(DWORD*)(vTable + 0x15C) = color;
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {}
}

std::string purchasingPriceSearch = xorstr("purchasing price");

string loadingArray[] =
{
	xorstr("Allocating Terrain..."),
	xorstr("Loading "),
	xorstr("Loading Effect Data..."),
	xorstr("Loading River Data..."),
	xorstr("Loading Terrain Patch Data..."),
	xorstr("Loading Terrain Tile Data..."),
	xorstr("Loading Terrain Grass Data..."),
	xorstr("Loading Lightmap Data..."),
	xorstr("Loading colormap"),
	xorstr("Loading Objects..."),
	xorstr("Loading Character Data..."),
	xorstr("Loading Information") ,
	xorstr("Loading Information[1]..."),
	xorstr("Loading Information[2]..."),
	xorstr("Loading Information[3]..."),
	xorstr("Loading Information[4]..."),
	xorstr("Loading Information[5]..."),
	xorstr("Loading Information[6]..."),
	xorstr("Loading Information[7]..."),
	xorstr("Loading Information[8]..."),
	xorstr("Loading Information[9]..."),
	xorstr("Loading Information[10]...")
};
bool isFindAdress = false;
bool checkkk = false;
bool isFalsed = false;
DWORD KO_CHR = *(DWORD*)KO_PTR_CHR;
bool MerchantPriceView(uint8& PriceType, uint32& Price)
{
	if (Engine->IsVisible(Engine->merchantdisplaydata))
	{
		if (sSocketMerchant > 10000 || sSocketMerchant < 1)
			return 0;
		PriceType = 0;
		Price = 0;
		uint8 getdata = 0;
		bool yoklama = false;
		for (int i = 0; i < 4; i++)
		{
			if (Engine->IsIn(Engine->merchantdisplayItem[i], Engine->lastMousePos.x, Engine->lastMousePos.y))
			{
				// UYARI GİDERİLDİ: int -> uint8
				getdata = (uint8)i;
				yoklama = true;
				break;
			}
		}
		if (yoklama)
		{
			Engine->merchantItemsPriceLock.lock();
			foreach(it, Engine->merchantItemsPrice)
			{
				if (it->first != sSocketMerchant)
					continue;

				for (int i = 0; i < 4; i++)
				{
					if (it->second.bSrcPos[i] != getdata)
						continue;

					PriceType = it->second.isKC[i];
					Price = it->second.price[i];
					break;
				}
				if (Price > 0)
					break;
			}
			Engine->merchantItemsPriceLock.unlock();
			return true;
		}
	}
	else if (Engine->IsVisible(Engine->merchantdisplaySpecialdata))
	{
		if (sSocketMerchantSpecial > 10000 || sSocketMerchantSpecial < 1)
			return 0;
		PriceType = 0;
		Price = 0;
		uint8 getdata = 0;
		bool yoklama = false;
		for (int i = 0; i < 8; i++)
		{
			if (Engine->IsIn(Engine->merchantdisplaySpecialItem[i], Engine->lastMousePos.x, Engine->lastMousePos.y))
			{
				// UYARI GİDERİLDİ: int -> uint8
				getdata = (uint8)i;
				yoklama = true;
				break;
			}
		}

		if (yoklama)
		{
			Engine->merchantItemsPriceLock.lock();
			foreach(it, Engine->merchantItemsPrice)
			{
				if (it->first != sSocketMerchantSpecial)
					continue;

				for (int i = 0; i < 8; i++)
				{

					if (it->second.bSrcPos[i] != getdata)
						continue;

					PriceType = it->second.isKC[i];
					Price = it->second.price[i];
					break;
				}
				if (Price > 0)
					break;
			}
			Engine->merchantItemsPriceLock.unlock();
			return true;
		}
	}

	return false;
}
clock_t recvTick2 = 0;
void __fastcall ThreadControlAlive()
{
	if (recvTick2 > clock() - 18000)
		return;

	recvTick2 = clock();

	if (CheckAliveTime < clock() - 18000)
	{
		//printf("THETHYKE | EXCEPTION 2\n");
		ischeatactive = true;
		Engine->StayAlive();

	}
	else if (Real_SendTime < clock() - 18000)
	{
		//printf("THETHYKE | EXCEPTION 3\n");
		ischeatactive = true;
		Engine->StayAlive();

	}
}

void __stdcall SetString_Hook(const std::string & szString)
{

	DWORD thisPtr;
	DWORD UIBase;
	__asm
	{
		MOV thisPtr, ECX
		MOV UIBase, ESI
	}

	bool test = false;
#if (HOOK_SOURCE_VERSION == 1098)	
	if (!Engine->m_bHookStart && Engine->Adress > 0 && !Engine->Loading && !isFalsed)		// 1098 KArakter Seçme ekrani ui pozisyonu ayarlanan yer
	{
		DWORD parenta;
		if (true)
		{

			Engine->GetChildByID(Engine->Adress, "Group_SelectWindow", parenta);
			DWORD KO_UI_SCREEN_SIZE = 0x00DFC99C;
			POINT koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
			RECT region = Engine->GetUiRegion(parenta);
			POINT orta;
			LONG w = (region.right - region.left);
			orta.x = (koScreen.x / 2) - 512;
			orta.y = region.top;
			Engine->SetUIPos(parenta, orta);

		}

		if (true)
		{
			DWORD parent;
			DWORD button;
			DWORD KO_UI_SCREEN_SIZE = 0x00DFC99C;
			POINT koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
			RECT region = Engine->GetUiRegion(parenta);
			Engine->GetChildByID(Engine->Adress, "Group_OtherCharacter", parent);
			Engine->GetChildByID(parenta, "btn_exit", button);
			POINT regiony = Engine->GetUiPos(button);
			regiony.x = (koScreen.x / 2) - 512;
			regiony.y -= 6;
			Engine->SetUIPos(parent, regiony);

		}
	}
#elif (HOOK_SOURCE_VERSION == 1534)	
	if (!Engine->m_bHookStart && Engine->Adress > 0 && !Engine->Loading && !isFalsed)			// 1534 KArakter Seçme ekrani ui pozisyonu ayarlanan yer
	{
		DWORD parenta;
		if (true)
		{

			Engine->GetChildByID(Engine->Adress, "Group_SelectWindow", parenta);
			DWORD KO_UI_SCREEN_SIZE = 0x00DFC99C;
			POINT koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
			RECT region = Engine->GetUiRegion(parenta);
			POINT orta;
			LONG w = (region.right - region.left);
			orta.x = (koScreen.x / 2) - 512;
			orta.y = koScreen.y - Engine->GetUiHeight(parenta);
			Engine->SetUIPos(parenta, orta);

		}

		if (true)
		{
			DWORD parent;
			Engine->GetChildByID(Engine->Adress, "Group_OtherCharacter", parent);
			DWORD KO_UI_SCREEN_SIZE = 0x00DFC99C;
			POINT koScreen = *(POINT*)KO_UI_SCREEN_SIZE;
			RECT region = Engine->GetUiRegion(parent);
			POINT orta;
			LONG w = (region.right - region.left);
			orta.x = (koScreen.x / 2) - 512;
			orta.y = koScreen.y - Engine->GetUiHeight(parent) - 65;
			Engine->SetUIPos(parent, orta);

		}
	}
#endif

	m_strReplaceString = szString;
	if (Engine->m_bHookStart && Engine->uiState->m_strFreeStatPoint == thisPtr)
	{
		int FreePoint = std::stoi(m_strReplaceString.c_str());
		if (FreePoint < 1)
			Engine->uiState->UpdatePointButton(false);
		else 	if (FreePoint > 0)
			Engine->uiState->UpdatePointButton(true);
	}

	if (Engine->m_bHookStart)
	{
		if (Engine->Player.ZoneID == 30)
			Engine->str_replace(m_strReplaceString, "Mission termination time....", "Castle Siege War Time : ");

		//if (Engine->IsVisible(Engine->uiTradeInventory->m_dVTableAddr))
		//{
		//	if (thisPtr == Engine->uiTradeInventory->text_sell_money)
		//	{
		//		if (stoi(m_strReplaceString) > 0)
		//		{
		//			if (nisKC == 1)

		//			{
		//				std::string currentTotalKC = Engine->GetString(Engine->uiTradeInventory->text_sell_KnightCash).c_str();
		//				if (currentTotalKC.empty())currentTotalKC = "0";
		//				std::string currentTotalCoins = Engine->GetString(Engine->uiTradeInventory->text_sell_money).c_str();
		//				uint32 nCoinsPriceCoins = stoi(currentTotalCoins);
		//				uint32 nCoinsPriceKC = stoi(currentTotalKC);
		//				nCoinsPriceKC += RecvPrice;
		//				Engine->SetString(Engine->uiTradeInventory->text_sell_KnightCash, string_format("%s", Engine->number_format(nCoinsPriceKC).c_str()));
		//				m_strReplaceString = string_format("%s", Engine->number_format(nCoinsPriceCoins).c_str());

		//			}
		//			else if (nisKC == 0)
		//			{
		//				std::string currentTotalCoins = Engine->GetString(Engine->uiTradeInventory->text_sell_money).c_str();
		//				if (currentTotalCoins.empty())currentTotalCoins = "0";
		//				//	if(currentTotalCoins=="0")Engine->SetString(Engine->uiTradeInventory->text_sell_KnightCash,"0");
		//				uint32 nCoinsPriceCoins = stoi(currentTotalCoins);

		//				nCoinsPriceCoins += RecvPrice;

		//				m_strReplaceString = string_format("%s", Engine->number_format(nCoinsPriceCoins).c_str());

		//			}
		//		}
		//	}
		//}
	}

	//PREMIUM CLAN yazisini clan premiuma çevirdik
	if (Engine->StringHelper->IsContains(m_strReplaceString, xorstr("PREMIUM")) && Engine->m_bHookStart) {

		if (Engine->GetStringElementName(thisPtr) == "text" && !Engine->StringHelper->IsContains(m_strReplaceString, xorstr("PC CAFE")))
		{
			DWORD nbase;
			std::string find = "btn_premium";
			Engine->GetChildByID(UIBase, find, nbase);
			find = "btn_clanpremium";
			Engine->GetChildByID(nbase, find, nbase);
			Engine->SetVisible(nbase, false);
		}
	}
	//*************************************

	for (auto a : Engine->privatemessages)
		if (thisPtr == a->exit_id)
		{
			a->user_id = m_strReplaceString;
			a->m_bcolored = true;
		}

	if (Engine->StringHelper == NULL)
		Engine->StringHelper = new CStringHelper();

	if (Engine->uiGenieSubPlug != NULL && Engine->uiGenieSubPlug->m_textGenieTime == thisPtr)
	{
		if (Engine->Genie1TimeCheck)
		{
			//xtreme level 10 geçince genie gözükür
			/*if (m_strReplaceString == "0")
			{
				if (Engine->IsVisible(Engine->uiGenieSubPlug->m_dVTableAddr))
				{
					Engine->SetVisible(Engine->uiGenieSubPlug->m_dVTableAddr, false);
				}
				Engine->GenieStartControl = false;
			}
			else
			{*/
			if (!Engine->IsVisible(Engine->uiGenieSubPlug->m_dVTableAddr))
			{
				Engine->GenieStartControl = true;
				Ayarlamk(Engine->hkServerNotice);
				Engine->SetVisible(Engine->uiGenieSubPlug->m_dVTableAddr, true);
			}
			Engine->GenieStartControl = true;
			//}
		}
		m_strReplaceString = string_format("Time Left : %s Hour(s)", m_strReplaceString.c_str());
	}
	if (!Engine->m_bHookStart) {
		if (Engine->m_bGameStart || Engine->StringHelper->IsContains(m_strReplaceString, xorstr("Loading Information[")))
			StartHook();
	}

	for (string larr : loadingArray)
	{
		if (Engine->StringHelper->IsContains(m_strReplaceString, larr))
		{
			Engine->Loading = true;
			test = true;
		}
	}

	if (Engine->m_SettingsMgr != NULL)
	{
		string ServerIniVer = Engine->m_SettingsMgr->ClientVersion;
		if (ServerIniVer == "0")
		{
			Engine->Loading = false;
		}

		string Ver = "Ver. ";
		string ValidVersion = Ver + "" + ServerIniVer.substr(0, 1) + "." + ServerIniVer.substr(1);
		if (m_strReplaceString == ValidVersion)
		{
			Engine->Loading = true;
			test = true;
			Engine->LoadingControl = true;
		}
	}
	else
	{
		Engine->Loading = true;
		test = true;
		Engine->LoadingControl = true;
	}

	if (Engine->LoqOut || Engine->Player.isTeleporting)
	{
		Engine->Loading = true;
		test = true;
	}

	if (!test && !Engine->LoadingControl)
		Engine->Loading = false;

	if (Engine->uiHpMenuPlug != NULL)
		Engine->uiHpMenuPlug->UpdatePosition();
	if (Engine->m_bGameStart)
	{
		if (Engine->uiHpMenuPlug != NULL && Engine->IsVisible(Engine->uiHPBarPlug->m_dVTableAddr) && !Engine->IsVisible(Engine->uiHpMenuPlug->m_dVTableAddr))
		{
			Engine->uiHpMenuPlug->OpenHpBarMenu();
			Engine->m_UiMgr->ShowAllUI();
		}

		// OPTİMİZASYON: Tooltip (İtem İkonu) Kasması Fixi!
		// Her frame'de string'i küçültüp aramak (str_contains) oyunu kilitler.
		// Sadece uzunluğu 10'dan büyükse ve 'P', 'p', 'K' veya 'k' harfleriyle başlıyorsa C++ 'find' ile hızlıca arıyoruz.
		if (m_strReplaceString.length() > 10 &&
			(m_strReplaceString[0] == 'P' || m_strReplaceString[0] == 'p' || m_strReplaceString[0] == 'K' || m_strReplaceString[0] == 'k'))
		{
			bool isPriceStr = (m_strReplaceString.find("urchasing price") != std::string::npos) ||
				(m_strReplaceString.find("urchasing Price") != std::string::npos);

			if (isPriceStr)
			{
				if (Engine->m_MerchantMgr != NULL && (Engine->m_MerchantMgr->NeedToCheckTooltip() || Engine->m_MerchantMgr->NeedToCheckDisplayTooltip()))
				{
					if (Engine->m_MerchantMgr->UpdateTooltipString(m_strReplaceString)) // kc ise renk degistir
						Engine->SetStringColor(thisPtr, 0xff7a70);
				}

				if ((Engine->merchantdisplaydata > 0 && Engine->IsVisible(Engine->merchantdisplaydata))
					|| (Engine->merchantdisplaySpecialdata > 0 && Engine->IsVisible(Engine->merchantdisplaySpecialdata)))
				{
					if (!Engine->m_MerchantMgr->IsMerchanting())
					{
						// UYARI GİDERİLDİ: 'nPrice' gizleme hatasını çözmek için 'localPrice' yapıldı.
						uint32 localPrice;
						uint8 isKC;
						if (MerchantPriceView(isKC, localPrice))
						{
							if (isKC)
								m_strReplaceString = string_format("Knight Cash Price : %s", Engine->number_format(localPrice, false).c_str());
							else
								m_strReplaceString = string_format("Purchasing Price : %s", Engine->number_format(localPrice, false).c_str());
						}
					}
				}
			}
		}
	} // EKSİK OLAN PARANTEZ BURAYA EKLENDİ

	_asm
	{
		MOV ECX, thisPtr
		MOV EAX, OFFSET m_strReplaceString

		PUSH EAX
		CALL KO_SET_STRING_FUNC
		call ThreadControlAlive
	}
}

void PearlEngine::InitSetString()
{
	*(DWORD*)KO_SET_STRING_PTR = (DWORD)SetString_Hook;
}

void __declspec(naked) IsInAsm()
{
	_asm
	{
		MOV ECX, [m_dvTable]
		MOV EAX, m_iParam2
		PUSH EAX
		MOV EAX, m_iParam1
		PUSH EAX
		CALL KO_UIBASE_IS_IN_FUNC
		MOV m_dBool, EAX
		RET
	}
}


void PearlEngine::SetItemFlag(DWORD vTable, uint8 flag)
{
	DWORD tmp = vTable;
	if (!tmp) return;
	__asm {
		mov ecx, tmp
		movsx eax, flag
		push eax
		call KO_UIF_SET_ITEM_FLAG
	}
}
// UYARI GİDERİLDİ: 'x' ve 'y' kullanılmadığı için yorum satırına alındı (C4100)
bool PearlEngine::IsIn(DWORD vTable, int /*x*/, int /*y*/)
{
	if (vTable == 0)
		return false;

	POINT pt = GetUiPos(vTable);
	LONG w = GetUiWidth(vTable);
	LONG h = GetUiHeight(vTable);

	RECT rp;
	rp.left = pt.x;
	rp.right = pt.x + w;
	rp.top = pt.y;
	rp.bottom = pt.y + h;

	return lastMousePos.x >= rp.left && lastMousePos.x <= rp.right && lastMousePos.y >= rp.top && lastMousePos.y <= rp.bottom;
}

bool PearlEngine::fileExist(const char* fileName)
{
	std::ifstream infile(string(m_BasePath + fileName).c_str());
	return infile.good();
}

LONG PearlEngine::GetUiWidth(DWORD vTable)
{
	uintptr_t** ptrVtable = (uintptr_t**)vTable;
	LONG right = (LONG)ptrVtable[61];
	LONG left = (LONG)ptrVtable[59];

	return right - left;
}

LONG PearlEngine::GetUiHeight(DWORD vTable)
{
	uintptr_t** ptrVtable = (uintptr_t**)vTable;
	LONG bottom = (LONG)ptrVtable[62];
	LONG top = (LONG)ptrVtable[60];

	return bottom - top;
}

size_t PearlEngine::GetScrollValue(DWORD vTable)
{
	DWORD track = *(DWORD*)(vTable + 0x134);
	return track ? *(uint32*)(track + 0x144) : 0;
}
bool PearlEngine::IsitaSandBox()
{
	unsigned char bBuffering = 0;

	// 1. Modül tutamacını al
	HMODULE hKernel32 = GetModuleHandleA(xorstr("KERNEL32.dll"));

	// 2. Güvenlik Kontrolü: Eğer modül bulunamazsa (NULL ise) işleme devam etme
	if (hKernel32 == nullptr)
		return false;

	// 3. Fonksiyon adresini al
	FARPROC aCreateProcesses = GetProcAddress(hKernel32, xorstr("CreateProcessA"));

	// 4. Güvenlik Kontrolü: Fonksiyon adresi bulunamazsa çökmemek için kontrol et
	if (aCreateProcesses == nullptr)
		return false;

	// 5. Belleği oku
	if (ReadProcessMemory(GetCurrentProcess(), (void*)aCreateProcesses, &bBuffering, 1, 0))
	{
		// 0xE9 (JMP) kontrolü: Eğer fonksiyon kancalanmışsa (hook) muhtemelen Sandbox/Debugger vardır
		if (bBuffering == 0xE9)
			return true;
	}

	return false;
}

bool PearlEngine::IsHWBreakpointExists()
{
	CONTEXT ctx;
	ZeroMemory(&ctx, sizeof(CONTEXT));
	ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
	HANDLE hThread = GetCurrentThread();
	if (GetThreadContext(hThread, &ctx) == 0)
		return false;

	if ((ctx.Dr0) || (ctx.Dr1) || (ctx.Dr2) || (ctx.Dr3))
		return true;
	else
		return false;
}

DWORD KO_ADR_CHR = 0x0;
DWORD KO_ADR_DLG = 0x0;

BYTE ReadByte(DWORD vTable)
{
	return *(byte*)vTable;
}

long ReadLong(DWORD vTable)
{
	return *(long*)vTable;
}

typedef void(__thiscall* tSetCurValue)(DWORD uiObject, float a1, float a2, float a3);
tSetCurValue Func_SetCurValue = (tSetCurValue)0x424B90;

void PearlEngine::SetCurValue(DWORD dwTable, float value, float changeSpeed)
{
	Func_SetCurValue(dwTable, value, 0, changeSpeed);
}
void PearlEngine::SetProgressRange(DWORD uif, float min, float max)
{
	DWORD tmp = uif;
	// UYARI GİDERİLDİ: 'float' -> 'DWORD' dönüşümü (C4244) için (DWORD) eklendi
	*(DWORD*)(uif + 0x150) = (DWORD)min;
	*(DWORD*)(uif + 0x14C) = (DWORD)max;
	__asm {
		mov eax, [tmp]
		mov eax, [eax]
		mov eax, [eax + 0xB0]
		mov ecx, tmp
		call eax
	}
}

void PearlEngine::ChangeRunState()
{
	__asm {
		mov ecx, [KO_PTR_CHR]
		mov ecx, [ecx]
		mov eax, 0x005751B0
		call eax
	}
}

void PearlEngine::CommandCameraChange()
{
	__asm {
		push - 1
		mov ecx, [0xF50FD8]
		mov ecx, [ecx]
		mov eax, 0x00A93940
		call eax
	}
}


long PearlEngine::SelectRandomMob()
{
	__asm {
		MOV ECX, KO_DLG
		MOV ECX, DWORD PTR DS : [ECX]
		MOV EAX, KO_FNCZ
		CALL EAX
	}
}
string PearlEngine::number_format(int dwNum, bool dot)
{
	std::string value = std::to_string(dwNum);
	// UYARI GİDERİLDİ: Olası bir 'size_t to int' veri kaybı uyarısını önlemek için cast eklendi.
	int len = (int)value.length();
	int dlen = 3;

	while (len > dlen)
	{
		value.insert(len - dlen, 1, dot ? '.' : ',');
		dlen += 4;
		len += 1;
	}

	return value;
}

void PearlEngine::str_tolower(std::string & str)
{
	for (size_t i = 0; i < str.length(); ++i)
		str[i] = (char)tolower(str[i]);
}

bool PearlEngine::str_contains(std::string str, std::string find)
{
	std::string s = str;
	str_tolower(s);

	std::string f = find;
	str_tolower(f);

	if (s.find(f) != std::string::npos)
		return true;
	return false;
}
std::string PearlEngine::GetItemDXT(int reqItemID)
{
	TABLE_ITEM_BASIC* tbl = Engine->tblMgr->getItemData(reqItemID);
	if (tbl != nullptr)
	{
		// OPTİMİZASYON: RAM şişiren std::vector kaldırıldı, sıfır gecikmeli statik char array eklendi.
		char buffer[128];
		sprintf_s(buffer, sizeof(buffer), "ui\\itemicon_%.1d_%.4d_%.2d_%.1d.dxt",
			(tbl->dxtID / 10000000),
			(tbl->dxtID / 1000) % 10000,
			(tbl->dxtID / 10) % 100,
			tbl->dxtID % 10);

		return std::string(buffer);
	}
	else
		return "UI\\itemicon_noimage.dxt";
}
void PearlEngine::str_replace(std::string & str, std::string find, std::string replace)
{
	if (find.empty())
		return;

	size_t start_pos = 0;
	while ((start_pos = str.find(find, start_pos)) != std::string::npos)
	{
		str.replace(start_pos, find.length(), replace);
		start_pos += replace.length();
	}
}
void PearlEngine::str_replace(std::string& str, char /*find*/, char /*replace*/)
{
	std::replace(str.begin(), str.end(), (char)25, (char)39); // replace all 'x' to 'y'
}

void PearlEngine::str_split(std::string const& str, const char delim, std::vector<std::string>&out)
{
	size_t start;
	size_t end = 0;

	while ((start = str.find_first_not_of(delim, end)) != std::string::npos)
	{
		end = str.find(delim, start);
		out.push_back(str.substr(start, end - start));
	}
}

void PearlEngine::str_split(std::string str, std::string delim, std::vector<std::string>&out)
{
	size_t pos_start = 0, pos_end, delim_len = delim.length();
	std::string token;

	while ((pos_end = str.find(delim, pos_start)) != std::string::npos)
	{
		token = str.substr(pos_start, pos_end - pos_start);
		pos_start = pos_end + delim_len;
		out.push_back(token);
	}

	out.push_back(str.substr(pos_start));
}

std::vector<std::string> PearlEngine::str_split(std::string str, std::string regex)
{
	std::smatch m;
	std::regex e(regex);
	std::vector<std::string> ret;

	while (std::regex_search(str, m, e))
	{
		for (string x : m)
			ret.push_back(x);
		str = m.suffix().str();
	}

	return ret;
}
std::string PearlEngine::KoRandomNameUIF(std::string uif)
{
	// UYARI GİDERİLDİ: C4996 uyumluluk uyarısı 'getpid' yerine '_getpid' kullanılarak çözüldü.
	srand((unsigned)time(NULL) * _getpid());
	int random1 = rand() % 10000;
	int random2 = rand() % 100;
	std::string text = string_format("%s_%d%d.uif", uif.c_str(), random1, random2);
	return text;
}

extern HCRYPTKEY hKey;

std::string PearlEngine::dcpUIF(std::string path)
{
	std::string rtn = "";
	if (!path.empty())
	{
		rtn = KoRandomNameUIF(path);
		PBYTE pbBuffer = NULL;
		HANDLE hSourceFile = CreateFileA(path.c_str(), FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		HANDLE hDestinationFile = CreateFileA(rtn.c_str(), FILE_WRITE_DATA, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
		if (INVALID_HANDLE_VALUE != hSourceFile && INVALID_HANDLE_VALUE != hDestinationFile)
		{
			bool fEOF = false;
			DWORD dwCount;
			LARGE_INTEGER size;
			GetFileSizeEx(hSourceFile, &size);
			LONGLONG len = size.QuadPart;
			DWORD dwBlockLen = len % 2 == 0 ? 32 : 31;
			DWORD dwBufferLen = dwBlockLen;
			if ((pbBuffer = (PBYTE)malloc(dwBufferLen)))
			{
				if (ReadFile(hSourceFile, pbBuffer, 4, &dwCount, NULL))
				{
					WriteFile(hDestinationFile, pbBuffer, dwCount, &dwCount, NULL);
				}
				ZeroMemory(pbBuffer, dwBufferLen);
				dwCount = 0;
				do
				{
					if (ReadFile(hSourceFile, pbBuffer, dwBlockLen, &dwCount, NULL))
					{
						if (dwCount < dwBlockLen)
						{
							fEOF = TRUE;
						}
						if (CryptDecrypt(hKey, 0, 1, 0, pbBuffer, &dwCount))
						{
							WriteFile(hDestinationFile, pbBuffer, dwCount, &dwCount, NULL);
						}
					}
				} while (!fEOF);
			}
		}
		if (pbBuffer)
		{
			free(pbBuffer);
		}
		if (hSourceFile)
		{
			CloseHandle(hSourceFile);
		}
		if (hDestinationFile)
		{
			CloseHandle(hDestinationFile);
		}
	}
	return rtn;
}

typedef void(__thiscall* tSetEditString)(DWORD ecx, const std::string& szString);
tSetEditString __SetEditString = (tSetEditString)0x4189A0;
typedef const std::string& (__thiscall* tGetEditString)(DWORD ecx);
tGetEditString __GetEditString = (tGetEditString)0x416960;

std::string PearlEngine::GetEditString(DWORD vTable)
{
	return __GetEditString(vTable);
}

void PearlEngine::SetEditString(DWORD vTable, const std::string & szString)
{
	__SetEditString(vTable, szString);
}

void ShowToolTip(__IconItemSkillEx * spItem, LONG x, LONG y)
{
	DWORD tooltipUI = 0;
	__asm {
		mov ecx, [KO_UI_DLG]
		mov ecx, [ecx]
		mov tooltipUI, ecx
	}

	int _type = 0;
	LONG _x = x, _y = y;

	__asm {
		push 0
		push 0
		push 1
		push 0 // istedigi np gosterilsin mi?
		push 1
		push 1 // 1 selling price // 2 buying price
		push 0 // show price
		push _type // inventory / merchant / drop hangisiysey onu yazar
		push spItem
		push _y
		push _x
		mov ecx, tooltipUI
		call KO_UI_TOOLTIP_FNC
	}
}

void PearlEngine::_ShowToolTip(DWORD spItem, LONG x, LONG y, TOOLTIP_TYPE type)
{
	DWORD tooltipUI = 0;
	__asm {
		mov ecx, [KO_UI_DLG]
		mov ecx, [ecx]
		mov tooltipUI, ecx
	}

	int _type = (int)type;
	LONG _x = x, _y = y;

	__asm {
		push 0
		push 0
		push 1
		push 0 // istedigi np gosterilsin mi
		push 0
		push 1 // 1 = selling price, 2 = buy price
		push 0 // show price
		push _type // tip ? yani inventory, merchant, drop
		push spItem
		push _y
		push _x
		mov ecx, tooltipUI
		call KO_UI_TOOLTIP_FNC
	}
}
// UYARI GİDERİLDİ: 'uif' parametresi (C4100) yorum satırına alındı
void __declspec(naked) SetN3UIIcon(DWORD* /*uif*/)
{
	__asm {
		push ebp
		mov ebp, esp
		push esi
		mov esi, [ebp + 8]
		mov ecx, [esi]
		call KO_UIF_SET_N3ICON
		mov[esi], eax
		pop esi
		pop ebp
		ret
	}
}
// UYARI GİDERİLDİ: 'uif' parametresi (C4100) yorum satırına alındı
void __declspec(naked) SetUVRect(DWORD /*uif*/, float /*left*/, float /*top*/, float /*right*/, float /*bottom*/)
{
	__asm {
		push ebp
		mov ebp, esp
		movss xmm0, [ebp + 0x18]
		sub esp, 0x20
		mov ecx, [ebp + 8]
		mov[esp + 0x1C], 0
		mov[esp + 0x18], 0
		mov[esp + 0x14], 0
		mov[esp + 0x10], 0
		movss[esp + 0xC], xmm0
		movss xmm0, [ebp + 0x14]
		movss[esp + 8], xmm0
		movss xmm0, [ebp + 0x10]
		movss[esp + 4], xmm0
		movss xmm0, [ebp + 0xC]
		movss[esp], xmm0
		call dword ptr[KO_UIF_IMG_SETUVRECT]
		pop ebp
		ret
	}
}
DWORD __fastcall __new(size_t allocSize)
{
	DWORD result = 0;
	try {
		// UYARI GİDERİLDİ: Koşul içinde atama (C4706) hatası çözüldü. Atama ve kontrol ayrıldı.
		result = (DWORD)malloc(allocSize);
		if (result != NULL) {
			memset((void*)result, 0, allocSize);
		}
	}
	catch (const std::bad_alloc&) {
		return NULL;
	}
	return result;
}

void SetParent(DWORD uif, DWORD parent)
{
	__asm {
		mov ecx, uif
		mov eax, [ecx]
		mov eax, [eax + 0x80]
		push parent
		call eax
	}
}

extern TABLE_ITEM_BASIC* GetItemBase(DWORD ItemID);
extern TABLE_ITEM_EXT* GetItemExtBase(DWORD dwItemNum, DWORD bExtIndex);

DWORD InitIcon(DWORD itemID)
{
	DWORD parent = *(DWORD*)KO_UI_MGR;
	CItem* item = (CItem*)GetItemBase(itemID);
	if (!item) return false;
	CItemExt* itemExt = (CItemExt*)GetItemExtBase(itemID, item->extNum);
	DWORD dwIconID = item->dxtID;
	if (itemExt && itemExt->iconID > 1000000)
		dwIconID = itemExt->iconID;

	std::string dxt = string_format(xorstr("UI\\ItemIcon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

	DWORD icon = __new(0x2A0);
	SetN3UIIcon(&icon);
	SetParent(icon, parent);
	Engine->SetTexImage(icon, dxt);
	SetUVRect(icon, 0.0f, 0.0f, 0.703125f, 0.703125f);
	*(DWORD*)(icon + 0xDC) = 11;
	__asm {
		mov ecx, icon
		push 0x110
		mov eax, [ecx]
		mov eax, [eax + 0x4C]
		call eax
		mov ecx, icon
		push 0
		mov eax, [ecx]
		mov eax, [eax + 0x50]
		call eax
	}
	return icon;
}

bool PearlEngine::_InitIcon(DWORD & iconObject, DWORD parent, DWORD itemID)
{
	CItem* item = (CItem*)GetItemBase(itemID);
	if (!item)
		return false;

	CItemExt* itemExt = (CItemExt*)GetItemExtBase(itemID, item->extNum);
	if (!itemExt)
		return false;

	DWORD dwIconID = item->dxtID;
	if (itemExt->dxtID > 0)
		dwIconID = itemExt->dxtID;


	//std::string dxt = string_format(xorstr("UI\\Itemicon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

	std::string dxt = "";
	if (itemID / 1000000000 - 1 > 2)
		dxt = string_format(xorstr("UI\\ItemIcon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);
	else
		dxt = string_format(xorstr("UI\\ItemIcon_%.2d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

	if (iconObject)
	{
		DWORD icon = iconObject;
		SetParent(icon, parent);
		SetTex(icon, dxt);
		SetUVRect(icon, 0.0f, 0.0f, 0.703125f, 0.703125f);
		__asm {
			mov ecx, icon
			push 1
			mov eax, [ecx]
			mov eax, [eax + 0x50]
			call eax
		}

		iconObject = icon;
		return true;
	}

	DWORD icon = __new(0x2A0);
	SetN3UIIcon(&icon);
	SetParent(icon, parent);
	Engine->SetTexImage(icon, dxt);
	SetUVRect(icon, 0.0f, 0.0f, 0.703125f, 0.703125f);
	*(DWORD*)(icon + 0xDC) = 11; // SetUIType(UI_TYPE_ICON);
	__asm { // SetStyle(UISTYLE_ICON_ITEM|UISTYLE_ICON_CERTIFICATION_NEED);
		mov ecx, icon
		push 0x110
		mov eax, [ecx]
		mov eax, [eax + 0x4C]
		call eax
		// -------------- setvisible true
		mov ecx, icon
		push 1
		mov eax, [ecx]
		mov eax, [eax + 0x50]
		call eax
	}
	iconObject = icon;
	return true;
}

// UYARI GİDERİLDİ (C4100): 'uif' parametresi asm içinde kullanıldığı için yoruma alındı.
void __declspec(naked) SetIconItemSkill(__IconItemSkillEx* /*uif*/)
{
	__asm {
		push ebp
		mov ebp, esp
		mov ecx, [ebp + 8]
		call KO_UIF_ICONITEMSKILL_SET
		pop ebp
		ret
	}
}

void PearlEngine::SetRegion(DWORD dwTable, DWORD uif)
{
	if (!dwTable)return;
	DWORD tmpTp = dwTable;
	DWORD otherRect = uif + UI_POS;
	__asm {
		mov ecx, tmpTp
		mov eax, [ecx]
		mov eax, [eax + 0x38]
		push otherRect
		call eax
	}
	*(RECT*)(dwTable + 0xFC) = *(RECT*)(dwTable + UI_POS);
}

// UYARI GİDERİLDİ (C4100): 'uif' parametresi asm içinde kullanıldığı için yoruma alındı.
void __declspec(naked) _SetIconItemSkill(DWORD* /*uif*/)
{
	__asm {
		push ebp
		mov ebp, esp
		push esi
		mov esi, [ebp + 8]
		mov ecx, [esi]
		call KO_UIF_ICONITEMSKILL_SET
		pop esi
		pop ebp
		ret
	}
}

// UYARI GİDERİLDİ (C4100): 'dwTable' ve 'szString' asm içinde kullanıldığı için yoruma alındı.
void __declspec(naked) _IntoString(DWORD /*dwTable*/, std::string& /*szString*/)
{
	__asm {
		push ebp
		mov ebp, esp
		mov ecx, [ebp + 8]
		push[ebp + 0xC]
		call KO_UIF_LOADSTRING
		pop ebp
		ret
	}
}

DWORD PearlEngine::_CreateIconItemSkill(DWORD self, DWORD UIIcon, DWORD itemID, short count, uint32 expiration, uint16 rental_remTime, uint32 rental_period, uint32 rental_price)
{
	CItem* item = (CItem*)GetItemBase(itemID);
	if (!item)
		return NULL;

	CItemExt* itemExt = (CItemExt*)GetItemExtBase(itemID, item->extNum);
	if (!itemExt)
		return NULL;

	DWORD dwIconID = item->dxtID;
	if (itemExt && itemExt->iconID > 1000000)
		dwIconID = itemExt->dxtID;

	std::string dxt = string_format(xorstr("UI\\ItemIcon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

	DWORD spItem = self;
	if (!spItem) {
		DWORD tmp = __new(0x78);
		if (tmp)
		{
			__asm {
				mov ecx, tmp
				call KO_UIF_ICONITEMSKILL_CREATE
				mov spItem, eax
			}
		}
	}

	if (!spItem) return NULL;

	__asm {
		mov ecx, spItem
		call KO_UIF_ICONITEMSKILL_SET
	}

	if (itemID == itemID)
		count = 0;

	_SetIconItemSkill(&spItem);
	_IntoString(spItem + KO_UIF_ICONITEMSKILL_OFF_DXT, dxt);
	*(uint16*)(spItem + KO_UIF_ICONITEMSKILL_OFF_RENT_TIME) = rental_remTime; // rental remaining time uint16
	*(uint32*)(spItem + KO_UIF_ICONITEMSKILL_OFF_RENT_PREIOD) = rental_period; // rental period minute uint32
	*(uint32*)(spItem + KO_UIF_ICONITEMSKILL_OFF_RENT_PRICE) = rental_price; // rental price uint32
	*(uint32*)(spItem + KO_UIF_ICONITEMSKILL_OFF_EXPIRATION) = expiration; // expiration time
	*(DWORD*)(spItem + KO_UIF_ICONITEMSKILL_OFF_ITEM) = (DWORD)item;
	*(DWORD*)(spItem + KO_UIF_ICONITEMSKILL_OFF_ITEM_EXT) = (DWORD)itemExt;
	*(short*)(spItem + KO_UIF_ICONITEMSKILL_OFF_ITEM_COUNT) = count;
	*(short*)(spItem + KO_UIF_ICONITEMSKILL_OFF_ITEM_DURATION) = item->Duration + itemExt->siMaxDurability;
	*(DWORD*)spItem = UIIcon;
	return spItem;
}

__IconItemSkillEx* CreateIconItemSkill(DWORD UIIcon, DWORD itemID, short count, uint32 expiration, uint16 rental_remTime, uint32 rental_period, uint32 rental_price)
{
	CItem* item = (CItem*)GetItemBase(itemID);
	if (!item)
		return NULL;

	CItemExt* itemExt = (CItemExt*)GetItemExtBase(itemID, item->extNum);

	DWORD dwIconID = item->dxtID;
	if (itemExt && itemExt->iconID > 1000000)
		dwIconID = itemExt->iconID;

	std::string dxt = string_format(xorstr("UI\\ItemIcon_%.1d_%.4d_%.2d_%.1d.dxt"), dwIconID / 10000000u, dwIconID / 1000u % 10000, dwIconID / 10u % 100, dwIconID % 10);

	__IconItemSkillEx* spItem = NULL;

	DWORD tmp = __new(0x78);
	if (tmp)
	{
		__asm {
			mov ecx, tmp
			call KO_UIF_ICONITEMSKILL_CREATE
			mov spItem, eax
		}
	}

	if (!spItem) return NULL;

	__asm {
		mov ecx, spItem
		call KO_UIF_ICONITEMSKILL_SET
	}

	SetIconItemSkill(spItem);

	spItem->pUIIcon = UIIcon;
	spItem->szIconFN = dxt;
	spItem->iRentTime = rental_remTime;
	spItem->iRentPeriod = rental_period;
	spItem->iRentPrice = rental_price;
	spItem->iExpiration = expiration;
	spItem->pItemBasic = item;
	spItem->pItemExt = itemExt;
	spItem->iCount = count;
	spItem->iDurability = item->Duration + (itemExt ? itemExt->siMaxDurability : 0);
	return spItem;
}

std::map <uint32, __IconItemSkillEx*> iconItemMap;

void PearlEngine::ShowToolTipEx(uint32 itemID, LONG x, LONG y)
{
	auto itr = iconItemMap.find(itemID);
	if (itr != iconItemMap.end())
	{
		ShowToolTip(itr->second, x, y);
		return;
	}

	if (DWORD icon = InitIcon(itemID))
	{
		if (__IconItemSkillEx* spItem = CreateIconItemSkill(icon, itemID, 1, 0, 0, 0, 0))
		{
			iconItemMap.insert(std::make_pair(itemID, spItem));
			ShowToolTip(spItem, x, y);
		}
	}
}

bool PearlEngine::IsGM()
{
	uint8 Authority = *(uint8*)(*(DWORD*)KO_PTR_CHR + KO_WH);
	if (Authority == 0)
		return true;

	return false;
}

// UYARI GİDERİLDİ (C4100): 'e' kullanılmadığı için yoruma alındı.
void PearlEngine::TimersV2(PearlEngine* /*e*/)
{
	while (true)
	{
		Sleep(1000);
		if (Engine->m_PlayerBase != NULL)
		{
			if (Engine->m_PlayerBase->m_iSlaveTime > 0)
				Engine->m_PlayerBase->m_iSlaveTime--;

			if (Engine->m_PlayerBase->m_iSlaveTime == 1)
			{
				Packet CloseMerc(XSafe, uint8(XSafeOpCodes::PL_SLAVE_MERC));
				CloseMerc << uint8(6) << uint8(0);
				Engine->Send(&CloseMerc);

				Packet CloseMerc2(XSafe, uint8(XSafeOpCodes::PL_SLAVE_MERC));
				CloseMerc2 << uint8(3) << uint8(1);
				Engine->Send(&CloseMerc2);
			}
		}
	}
}